xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision f1e762dd)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Generic widget tree parser
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  This driver is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
101da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
111da177e4SLinus Torvalds  *  (at your option) any later version.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *  This driver is distributed in the hope that it will be useful,
141da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
151da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4SLinus Torvalds  *  GNU General Public License for more details.
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  *  You should have received a copy of the GNU General Public License
191da177e4SLinus Torvalds  *  along with this program; if not, write to the Free Software
201da177e4SLinus Torvalds  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
211da177e4SLinus Torvalds  */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/slab.h>
25d81a6d71SPaul Gortmaker #include <linux/export.h>
26352f7f91STakashi Iwai #include <linux/sort.h>
2755196fffSTakashi Iwai #include <linux/delay.h>
28f873e536STakashi Iwai #include <linux/ctype.h>
29f873e536STakashi Iwai #include <linux/string.h>
3029476558STakashi Iwai #include <linux/bitops.h>
31b21bdd0dSTakashi Iwai #include <linux/module.h>
321da177e4SLinus Torvalds #include <sound/core.h>
33352f7f91STakashi Iwai #include <sound/jack.h>
341da177e4SLinus Torvalds #include "hda_codec.h"
351da177e4SLinus Torvalds #include "hda_local.h"
36352f7f91STakashi Iwai #include "hda_auto_parser.h"
37352f7f91STakashi Iwai #include "hda_jack.h"
387504b6cdSTakashi Iwai #include "hda_beep.h"
39352f7f91STakashi Iwai #include "hda_generic.h"
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 
42352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
43352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
441da177e4SLinus Torvalds {
45352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
46352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
470186f4f4STakashi Iwai 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
4838cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
49352f7f91STakashi Iwai 	return 0;
50352f7f91STakashi Iwai }
51352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
521da177e4SLinus Torvalds 
5312c93df6STakashi Iwai struct snd_kcontrol_new *
5412c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
55352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
56352f7f91STakashi Iwai {
57352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
58352f7f91STakashi Iwai 	if (!knew)
59352f7f91STakashi Iwai 		return NULL;
60352f7f91STakashi Iwai 	*knew = *temp;
61352f7f91STakashi Iwai 	if (name)
62352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
63352f7f91STakashi Iwai 	else if (knew->name)
64352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
65352f7f91STakashi Iwai 	if (!knew->name)
66352f7f91STakashi Iwai 		return NULL;
67352f7f91STakashi Iwai 	return knew;
68352f7f91STakashi Iwai }
6912c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
70352f7f91STakashi Iwai 
71352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
72352f7f91STakashi Iwai {
73352f7f91STakashi Iwai 	if (spec->kctls.list) {
74352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
75352f7f91STakashi Iwai 		int i;
76352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
77352f7f91STakashi Iwai 			kfree(kctl[i].name);
78352f7f91STakashi Iwai 	}
79352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
80352f7f91STakashi Iwai }
81352f7f91STakashi Iwai 
82352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
83352f7f91STakashi Iwai {
841da177e4SLinus Torvalds 	if (!spec)
851da177e4SLinus Torvalds 		return;
86352f7f91STakashi Iwai 	free_kctls(spec);
87352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
880186f4f4STakashi Iwai 	snd_array_free(&spec->loopback_list);
891da177e4SLinus Torvalds }
90352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds /*
931c70a583STakashi Iwai  * store user hints
941c70a583STakashi Iwai  */
951c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
961c70a583STakashi Iwai {
971c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
981c70a583STakashi Iwai 	int val;
991c70a583STakashi Iwai 
1001c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1011c70a583STakashi Iwai 	if (val >= 0)
1021c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1031c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1041c70a583STakashi Iwai 	if (val >= 0)
1051c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1061c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1071c70a583STakashi Iwai 	if (val >= 0)
1081c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1091c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1101c70a583STakashi Iwai 	if (val >= 0)
1111c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1121c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1131c70a583STakashi Iwai 	if (val >= 0)
1141c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1151c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1161c70a583STakashi Iwai 	if (val >= 0)
1171c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1181c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1191c70a583STakashi Iwai 	if (val >= 0)
1201c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1211c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1221c70a583STakashi Iwai 	if (val >= 0)
1231c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1241c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1251c70a583STakashi Iwai 	if (val >= 0)
1261c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
1271c70a583STakashi Iwai 
128f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
129f72706beSTakashi Iwai 	if (val >= 0)
130f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1311c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1321c70a583STakashi Iwai 	if (val >= 0)
1331c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1341c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1351c70a583STakashi Iwai 	if (val >= 0)
1361c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1377eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1387eebffd3STakashi Iwai 	if (val >= 0)
1397eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1401c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1411c70a583STakashi Iwai 	if (val >= 0)
1421c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1431c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1441c70a583STakashi Iwai 	if (val >= 0)
1451c70a583STakashi Iwai 		spec->no_primary_hp = !val;
146da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
147da96fb5bSTakashi Iwai 	if (val >= 0)
148da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1491c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1501c70a583STakashi Iwai 	if (val >= 0)
1511c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1521c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1531c70a583STakashi Iwai 	if (val >= 0)
1541c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1551c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1561c70a583STakashi Iwai 	if (val >= 0)
1571c70a583STakashi Iwai 		spec->indep_hp = !!val;
1581c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1591c70a583STakashi Iwai 	if (val >= 0)
1601c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
161f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1621c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1631c70a583STakashi Iwai 	if (val >= 0)
164f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
16529476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
16629476558STakashi Iwai 	if (val >= 0)
167f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
168f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
169f811c3cfSTakashi Iwai 	if (val >= 0)
170f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
17155196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
17255196fffSTakashi Iwai 	if (val >= 0)
17355196fffSTakashi Iwai 		spec->power_down_unused = !!val;
174967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
175967303daSTakashi Iwai 	if (val >= 0)
176967303daSTakashi Iwai 		spec->hp_mic = !!val;
177967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
178967303daSTakashi Iwai 	if (val >= 0)
179967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1801c70a583STakashi Iwai 
1811c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1821c70a583STakashi Iwai 		spec->mixer_nid = val;
1831c70a583STakashi Iwai }
1841c70a583STakashi Iwai 
1851c70a583STakashi Iwai /*
1862c12c30dSTakashi Iwai  * pin control value accesses
1872c12c30dSTakashi Iwai  */
1882c12c30dSTakashi Iwai 
1892c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
1902c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
1912c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
1922c12c30dSTakashi Iwai 
1932c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
1942c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
1952c12c30dSTakashi Iwai {
1962c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
1972c12c30dSTakashi Iwai }
1982c12c30dSTakashi Iwai 
1992c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2002c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2012c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2022c12c30dSTakashi Iwai {
2032c12c30dSTakashi Iwai 	if (!pin)
2042c12c30dSTakashi Iwai 		return;
2052c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2062c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2072c12c30dSTakashi Iwai 	if (do_write)
2082c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2092c12c30dSTakashi Iwai }
2102c12c30dSTakashi Iwai 
2112c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2122c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2132c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2142c12c30dSTakashi Iwai {
2152c12c30dSTakashi Iwai 	int i;
2162c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2172c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2182c12c30dSTakashi Iwai }
2192c12c30dSTakashi Iwai 
2202c12c30dSTakashi Iwai /*
221352f7f91STakashi Iwai  * parsing paths
2221da177e4SLinus Torvalds  */
2231da177e4SLinus Torvalds 
2243ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2253ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2263ca529d3STakashi Iwai {
2273ca529d3STakashi Iwai 	int i;
2283ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2293ca529d3STakashi Iwai 		if (list[i] == nid)
2303ca529d3STakashi Iwai 			return i;
2313ca529d3STakashi Iwai 	return -1;
2323ca529d3STakashi Iwai }
2333ca529d3STakashi Iwai 
2343ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2353ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2363ca529d3STakashi Iwai {
2373ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2383ca529d3STakashi Iwai }
2393ca529d3STakashi Iwai 
240f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
241f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2423ca529d3STakashi Iwai 				     int anchor_nid)
2431da177e4SLinus Torvalds {
244352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
245352f7f91STakashi Iwai 	int i;
2461da177e4SLinus Torvalds 
247352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
248352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
249352f7f91STakashi Iwai 		if (path->depth <= 0)
250352f7f91STakashi Iwai 			continue;
251352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
252f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2533ca529d3STakashi Iwai 			if (!anchor_nid ||
2543ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2553ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
256352f7f91STakashi Iwai 				return path;
2571da177e4SLinus Torvalds 		}
258f5172a7eSTakashi Iwai 	}
2591da177e4SLinus Torvalds 	return NULL;
2601da177e4SLinus Torvalds }
261f5172a7eSTakashi Iwai 
262f5172a7eSTakashi Iwai /* get the path between the given NIDs;
263f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
264f5172a7eSTakashi Iwai  */
265f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
266f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
267f5172a7eSTakashi Iwai {
2683ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
269f5172a7eSTakashi Iwai }
270352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
2711da177e4SLinus Torvalds 
272196c1766STakashi Iwai /* get the index number corresponding to the path instance;
273196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
274196c1766STakashi Iwai  */
275196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
276196c1766STakashi Iwai {
277196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
278196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
279196c1766STakashi Iwai 	ssize_t idx;
280196c1766STakashi Iwai 
281196c1766STakashi Iwai 	if (!spec->paths.used)
282196c1766STakashi Iwai 		return 0;
283196c1766STakashi Iwai 	idx = path - array;
284196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
285196c1766STakashi Iwai 		return 0;
286196c1766STakashi Iwai 	return idx + 1;
287196c1766STakashi Iwai }
2884bd01e93STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_path_idx);
289196c1766STakashi Iwai 
290196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
291196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
292196c1766STakashi Iwai {
293196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
294196c1766STakashi Iwai 
295196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
296196c1766STakashi Iwai 		return NULL;
297196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
298196c1766STakashi Iwai }
2994bd01e93STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_path_from_idx);
300196c1766STakashi Iwai 
301352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
302352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3031da177e4SLinus Torvalds {
304352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
305352f7f91STakashi Iwai 	int i;
306352f7f91STakashi Iwai 
307352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
308352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
309352f7f91STakashi Iwai 		if (path->path[0] == nid)
310352f7f91STakashi Iwai 			return true;
311352f7f91STakashi Iwai 	}
312352f7f91STakashi Iwai 	return false;
3131da177e4SLinus Torvalds }
3141da177e4SLinus Torvalds 
315352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
316352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
317352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3181da177e4SLinus Torvalds {
319352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
320352f7f91STakashi Iwai 		return false;
321352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3221da177e4SLinus Torvalds }
3231da177e4SLinus Torvalds 
324352f7f91STakashi Iwai /* nid, dir and idx */
325352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
326352f7f91STakashi Iwai 
327352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
328352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3291da177e4SLinus Torvalds {
330352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
331352f7f91STakashi Iwai 	int i;
332352f7f91STakashi Iwai 
333352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
334352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
335352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
336352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
337352f7f91STakashi Iwai 			return true;
338352f7f91STakashi Iwai 	}
339352f7f91STakashi Iwai 	return false;
3401da177e4SLinus Torvalds }
3411da177e4SLinus Torvalds 
342352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
343352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3448999bf0aSTakashi Iwai 			      int dir, int idx, int type)
345cb53c626STakashi Iwai {
346352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3478999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
348cb53c626STakashi Iwai }
349352f7f91STakashi Iwai 
3500c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
3510c8c0f56STakashi Iwai {
3520c8c0f56STakashi Iwai 	char buf[40];
3530c8c0f56STakashi Iwai 	int i;
3540c8c0f56STakashi Iwai 
3550c8c0f56STakashi Iwai 
3560c8c0f56STakashi Iwai 	buf[0] = 0;
3570c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
3580c8c0f56STakashi Iwai 		char tmp[4];
3590c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
3600c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
3610c8c0f56STakashi Iwai 	}
3620c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
3630c8c0f56STakashi Iwai }
3640c8c0f56STakashi Iwai 
365352f7f91STakashi Iwai /* called recursively */
366352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
367352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3683ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3693ca529d3STakashi Iwai 			     int depth)
370352f7f91STakashi Iwai {
371ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
372352f7f91STakashi Iwai 	int i, nums;
373352f7f91STakashi Iwai 
3743ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3753ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3763ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3773ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
378352f7f91STakashi Iwai 
379ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
380352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
381352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
382352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
383352f7f91STakashi Iwai 			 * try to find an empty DAC
384352f7f91STakashi Iwai 			 */
385352f7f91STakashi Iwai 			if (from_nid ||
386352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
387352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
388352f7f91STakashi Iwai 				continue;
389352f7f91STakashi Iwai 		}
3903ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
3913ca529d3STakashi Iwai 		if (anchor_nid <= 0)
392352f7f91STakashi Iwai 			goto found;
393352f7f91STakashi Iwai 	}
394352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
395352f7f91STakashi Iwai 		return false;
396352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
397352f7f91STakashi Iwai 		unsigned int type;
398352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
399352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
400352f7f91STakashi Iwai 		    type == AC_WID_PIN)
401352f7f91STakashi Iwai 			continue;
402352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4033ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
404352f7f91STakashi Iwai 			goto found;
405352f7f91STakashi Iwai 	}
406352f7f91STakashi Iwai 	return false;
407352f7f91STakashi Iwai 
408352f7f91STakashi Iwai  found:
409352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
410352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
411352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
412352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
413352f7f91STakashi Iwai 	path->depth++;
414352f7f91STakashi Iwai 	return true;
415352f7f91STakashi Iwai }
416352f7f91STakashi Iwai 
417352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
418352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4193ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4203ca529d3STakashi Iwai  * with the given value are evaluated.
4213ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4223ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4233ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
424352f7f91STakashi Iwai  */
425352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4263ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
427352f7f91STakashi Iwai 			    struct nid_path *path)
428352f7f91STakashi Iwai {
4293ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
430352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
431352f7f91STakashi Iwai 		path->depth++;
432352f7f91STakashi Iwai 		return true;
433352f7f91STakashi Iwai 	}
434352f7f91STakashi Iwai 	return false;
435352f7f91STakashi Iwai }
436352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
437352f7f91STakashi Iwai 
438352f7f91STakashi Iwai /*
439352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
440352f7f91STakashi Iwai  * if no valid path is found, return NULL
441352f7f91STakashi Iwai  */
442352f7f91STakashi Iwai struct nid_path *
443352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4443ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
445352f7f91STakashi Iwai {
446352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
447352f7f91STakashi Iwai 	struct nid_path *path;
448352f7f91STakashi Iwai 
449352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
450352f7f91STakashi Iwai 		return NULL;
451352f7f91STakashi Iwai 
452f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4533ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
454f5172a7eSTakashi Iwai 	if (path)
455f5172a7eSTakashi Iwai 		return path;
456f5172a7eSTakashi Iwai 
457352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
458352f7f91STakashi Iwai 	if (!path)
459352f7f91STakashi Iwai 		return NULL;
460352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4613ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
462352f7f91STakashi Iwai 		return path;
463352f7f91STakashi Iwai 	/* push back */
464352f7f91STakashi Iwai 	spec->paths.used--;
465352f7f91STakashi Iwai 	return NULL;
466352f7f91STakashi Iwai }
467352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
468352f7f91STakashi Iwai 
469980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
470980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
471980428ceSTakashi Iwai {
472980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
473980428ceSTakashi Iwai 	if (!path)
474980428ceSTakashi Iwai 		return;
475980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
476980428ceSTakashi Iwai }
477980428ceSTakashi Iwai 
478352f7f91STakashi Iwai /* look for an empty DAC slot */
479352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
480352f7f91STakashi Iwai 			      bool is_digital)
481352f7f91STakashi Iwai {
482352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
483352f7f91STakashi Iwai 	bool cap_digital;
484352f7f91STakashi Iwai 	int i;
485352f7f91STakashi Iwai 
486352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
487352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
488352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
489352f7f91STakashi Iwai 			continue;
490352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
491352f7f91STakashi Iwai 		if (is_digital != cap_digital)
492352f7f91STakashi Iwai 			continue;
493352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
494352f7f91STakashi Iwai 			return nid;
495352f7f91STakashi Iwai 	}
496352f7f91STakashi Iwai 	return 0;
497352f7f91STakashi Iwai }
498352f7f91STakashi Iwai 
499352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
500352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
501352f7f91STakashi Iwai {
502352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
503352f7f91STakashi Iwai 	val |= chs << 16;
504352f7f91STakashi Iwai 	return val;
505352f7f91STakashi Iwai }
506352f7f91STakashi Iwai 
507352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
508352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
509352f7f91STakashi Iwai 			   int dir, unsigned int bits)
510352f7f91STakashi Iwai {
511352f7f91STakashi Iwai 	if (!nid)
512352f7f91STakashi Iwai 		return false;
513352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
514352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
515352f7f91STakashi Iwai 			return true;
516352f7f91STakashi Iwai 	return false;
517352f7f91STakashi Iwai }
518352f7f91STakashi Iwai 
51999a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
52099a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
52199a5592dSDavid Henningsson {
52299a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
52399a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
52499a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
52599a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
52699a5592dSDavid Henningsson }
52799a5592dSDavid Henningsson 
528352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
529f69910ddSTakashi Iwai 	check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
530352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
531352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
532352f7f91STakashi Iwai 
533352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
534352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
535352f7f91STakashi Iwai 				       struct nid_path *path)
536352f7f91STakashi Iwai {
537352f7f91STakashi Iwai 	int i;
538352f7f91STakashi Iwai 
539352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
540352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
541352f7f91STakashi Iwai 			return path->path[i];
542352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
543352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
544352f7f91STakashi Iwai 			return path->path[i];
545352f7f91STakashi Iwai 	}
546352f7f91STakashi Iwai 	return 0;
547352f7f91STakashi Iwai }
548352f7f91STakashi Iwai 
549352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
550352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
551352f7f91STakashi Iwai 				      struct nid_path *path)
552352f7f91STakashi Iwai {
553a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
554352f7f91STakashi Iwai 	int i;
555352f7f91STakashi Iwai 
556352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
557a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
558a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
559a1114a8cSTakashi Iwai 			continue;
560a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
561a1114a8cSTakashi Iwai 			return nid;
562352f7f91STakashi Iwai 	}
563352f7f91STakashi Iwai 	return 0;
564352f7f91STakashi Iwai }
565352f7f91STakashi Iwai 
566352f7f91STakashi Iwai /*
567352f7f91STakashi Iwai  * path activation / deactivation
568352f7f91STakashi Iwai  */
569352f7f91STakashi Iwai 
570352f7f91STakashi Iwai /* can have the amp-in capability? */
571352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
572352f7f91STakashi Iwai {
573352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
574352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
575352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
576352f7f91STakashi Iwai 
577352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
578352f7f91STakashi Iwai 		return false;
579352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
580352f7f91STakashi Iwai 		return false;
581352f7f91STakashi Iwai 	return true;
582352f7f91STakashi Iwai }
583352f7f91STakashi Iwai 
584352f7f91STakashi Iwai /* can have the amp-out capability? */
585352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
586352f7f91STakashi Iwai {
587352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
588352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
589352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
590352f7f91STakashi Iwai 
591352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
592352f7f91STakashi Iwai 		return false;
593352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
594352f7f91STakashi Iwai 		return false;
595352f7f91STakashi Iwai 	return true;
596352f7f91STakashi Iwai }
597352f7f91STakashi Iwai 
598352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
599352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6007dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
601352f7f91STakashi Iwai {
602352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
603352f7f91STakashi Iwai 	int i, n;
604352f7f91STakashi Iwai 
605352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
606352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
607352f7f91STakashi Iwai 		if (!path->active)
608352f7f91STakashi Iwai 			continue;
609352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
610352f7f91STakashi Iwai 			if (path->path[i] == nid) {
611352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
612352f7f91STakashi Iwai 					return true;
613352f7f91STakashi Iwai 				break;
614352f7f91STakashi Iwai 			}
615352f7f91STakashi Iwai 		}
616352f7f91STakashi Iwai 	}
617352f7f91STakashi Iwai 	return false;
618352f7f91STakashi Iwai }
619352f7f91STakashi Iwai 
620b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
621b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
622b1b9fbd0STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, 0)
623b1b9fbd0STakashi Iwai 
624352f7f91STakashi Iwai /* get the default amp value for the target state */
625352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6268999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
627352f7f91STakashi Iwai {
628352f7f91STakashi Iwai 	unsigned int val = 0;
629352f7f91STakashi Iwai 
630352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
631352f7f91STakashi Iwai 		/* set to 0dB */
632352f7f91STakashi Iwai 		if (enable)
633352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
634352f7f91STakashi Iwai 	}
635f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
636352f7f91STakashi Iwai 		if (!enable)
637352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
638352f7f91STakashi Iwai 	}
639352f7f91STakashi Iwai 	return val;
640352f7f91STakashi Iwai }
641352f7f91STakashi Iwai 
642352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
643352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
644352f7f91STakashi Iwai {
6458999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6468999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
647352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
648352f7f91STakashi Iwai }
649352f7f91STakashi Iwai 
6508999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6518999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
6528999bf0aSTakashi Iwai  */
6538999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
6548999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
6558999bf0aSTakashi Iwai 					   unsigned int caps)
656352f7f91STakashi Iwai {
6578999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
6588999bf0aSTakashi Iwai 
659f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
6608999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
6618999bf0aSTakashi Iwai 			mask &= ~0x80;
6628999bf0aSTakashi Iwai 	}
6638999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
6648999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
6658999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
6668999bf0aSTakashi Iwai 			mask &= ~0x7f;
6678999bf0aSTakashi Iwai 	}
6688999bf0aSTakashi Iwai 	return mask;
6698999bf0aSTakashi Iwai }
6708999bf0aSTakashi Iwai 
6718999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
6728999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
6738999bf0aSTakashi Iwai {
6748999bf0aSTakashi Iwai 	unsigned int caps;
6758999bf0aSTakashi Iwai 	unsigned int mask, val;
6768999bf0aSTakashi Iwai 
6777dddf2aeSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
678352f7f91STakashi Iwai 		return;
6798999bf0aSTakashi Iwai 
6808999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
6818999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
6828999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
6838999bf0aSTakashi Iwai 	if (!mask)
6848999bf0aSTakashi Iwai 		return;
6858999bf0aSTakashi Iwai 
6868999bf0aSTakashi Iwai 	val &= mask;
6878999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
688352f7f91STakashi Iwai }
689352f7f91STakashi Iwai 
690352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
691352f7f91STakashi Iwai 			     int i, bool enable)
692352f7f91STakashi Iwai {
693352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
694352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
6958999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
696352f7f91STakashi Iwai }
697352f7f91STakashi Iwai 
698352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
699352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
700352f7f91STakashi Iwai {
701352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
702ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
703352f7f91STakashi Iwai 	int n, nums, idx;
704352f7f91STakashi Iwai 	int type;
705352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
706352f7f91STakashi Iwai 
707ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
708352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
709352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
710352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
711352f7f91STakashi Iwai 		nums = 1;
712352f7f91STakashi Iwai 		idx = 0;
713352f7f91STakashi Iwai 	} else
714352f7f91STakashi Iwai 		idx = path->idx[i];
715352f7f91STakashi Iwai 
716352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
717352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
718352f7f91STakashi Iwai 
719352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
720352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
721352f7f91STakashi Iwai 	 */
722352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
723e4a395e7STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
724352f7f91STakashi Iwai 			continue;
7258999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
726352f7f91STakashi Iwai 	}
727352f7f91STakashi Iwai }
728352f7f91STakashi Iwai 
729352f7f91STakashi Iwai /* activate or deactivate the given path
730352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
731352f7f91STakashi Iwai  */
732352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
733352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
734352f7f91STakashi Iwai {
73555196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
736352f7f91STakashi Iwai 	int i;
737352f7f91STakashi Iwai 
738352f7f91STakashi Iwai 	if (!enable)
739352f7f91STakashi Iwai 		path->active = false;
740352f7f91STakashi Iwai 
741352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
74255196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
74355196fffSTakashi Iwai 		if (enable && spec->power_down_unused) {
74455196fffSTakashi Iwai 			/* make sure the widget is powered up */
74555196fffSTakashi Iwai 			if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
74655196fffSTakashi Iwai 				snd_hda_codec_write(codec, nid, 0,
74755196fffSTakashi Iwai 						    AC_VERB_SET_POWER_STATE,
74855196fffSTakashi Iwai 						    AC_PWRST_D0);
74955196fffSTakashi Iwai 		}
750352f7f91STakashi Iwai 		if (enable && path->multi[i])
75155196fffSTakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
752352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
753352f7f91STakashi Iwai 					    path->idx[i]);
754352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
755352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
756352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
757352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
758352f7f91STakashi Iwai 	}
759352f7f91STakashi Iwai 
760352f7f91STakashi Iwai 	if (enable)
761352f7f91STakashi Iwai 		path->active = true;
762352f7f91STakashi Iwai }
763352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
764352f7f91STakashi Iwai 
76555196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
76655196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
76755196fffSTakashi Iwai {
76855196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
769868211dbSJiri Slaby 	bool changed = false;
77055196fffSTakashi Iwai 	int i;
77155196fffSTakashi Iwai 
77255196fffSTakashi Iwai 	if (!spec->power_down_unused || path->active)
77355196fffSTakashi Iwai 		return;
77455196fffSTakashi Iwai 
77555196fffSTakashi Iwai 	for (i = 0; i < path->depth; i++) {
77655196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
777b1b9fbd0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
778b1b9fbd0STakashi Iwai 		    !is_active_nid_for_any(codec, nid)) {
77955196fffSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
78055196fffSTakashi Iwai 					    AC_VERB_SET_POWER_STATE,
78155196fffSTakashi Iwai 					    AC_PWRST_D3);
78255196fffSTakashi Iwai 			changed = true;
78355196fffSTakashi Iwai 		}
78455196fffSTakashi Iwai 	}
78555196fffSTakashi Iwai 
78655196fffSTakashi Iwai 	if (changed) {
78755196fffSTakashi Iwai 		msleep(10);
78855196fffSTakashi Iwai 		snd_hda_codec_read(codec, path->path[0], 0,
78955196fffSTakashi Iwai 				   AC_VERB_GET_POWER_STATE, 0);
79055196fffSTakashi Iwai 	}
79155196fffSTakashi Iwai }
79255196fffSTakashi Iwai 
793d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
794d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
795d5a9f1bbSTakashi Iwai {
796d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
797d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
798d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
799d5a9f1bbSTakashi Iwai 		return;
80005909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
80105909d5cSTakashi Iwai 		return;
802468ac413STakashi Iwai 	if (codec->inv_eapd)
803468ac413STakashi Iwai 		enable = !enable;
804d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
805d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
806d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
807d5a9f1bbSTakashi Iwai }
808d5a9f1bbSTakashi Iwai 
8093e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
8103e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
8113e367f15STakashi Iwai {
8123e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
8133e367f15STakashi Iwai 	if (path)
8143e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
8153e367f15STakashi Iwai }
8163e367f15STakashi Iwai 
817352f7f91STakashi Iwai 
818352f7f91STakashi Iwai /*
819352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
820352f7f91STakashi Iwai  */
821352f7f91STakashi Iwai 
8227eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
8237eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
824bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
825bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
8267eebffd3STakashi Iwai 
827352f7f91STakashi Iwai enum {
828352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
829352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
830352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
831352f7f91STakashi Iwai };
832352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
833352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
8347eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
8357eebffd3STakashi Iwai 	{
8367eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8377eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
8387eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
8397eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
8407eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
8417eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
8427eebffd3STakashi Iwai 	},
843bc2eee29STakashi Iwai 	{
844bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
845bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
846bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
847bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
848bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
849bc2eee29STakashi Iwai 	},
850352f7f91STakashi Iwai };
851352f7f91STakashi Iwai 
852352f7f91STakashi Iwai /* add dynamic controls from template */
853a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
854a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
855352f7f91STakashi Iwai 		       int cidx, unsigned long val)
856352f7f91STakashi Iwai {
857352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
858352f7f91STakashi Iwai 
85912c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
860352f7f91STakashi Iwai 	if (!knew)
861a35bd1e3STakashi Iwai 		return NULL;
862352f7f91STakashi Iwai 	knew->index = cidx;
863352f7f91STakashi Iwai 	if (get_amp_nid_(val))
864352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
865352f7f91STakashi Iwai 	knew->private_value = val;
866a35bd1e3STakashi Iwai 	return knew;
867352f7f91STakashi Iwai }
868352f7f91STakashi Iwai 
869352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
870352f7f91STakashi Iwai 				const char *pfx, const char *dir,
871352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
872352f7f91STakashi Iwai {
873975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
874352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
875a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
876a35bd1e3STakashi Iwai 		return -ENOMEM;
877a35bd1e3STakashi Iwai 	return 0;
878352f7f91STakashi Iwai }
879352f7f91STakashi Iwai 
880352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
881352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
882352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
883352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
884352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
885352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
886352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
887352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
888352f7f91STakashi Iwai 
889352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
890352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
891352f7f91STakashi Iwai {
892352f7f91STakashi Iwai 	unsigned int val;
893352f7f91STakashi Iwai 	if (!path)
894352f7f91STakashi Iwai 		return 0;
895352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
896352f7f91STakashi Iwai 	if (!val)
897352f7f91STakashi Iwai 		return 0;
898352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
899352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
900352f7f91STakashi Iwai }
901352f7f91STakashi Iwai 
902352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
903352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
904352f7f91STakashi Iwai 			       int type)
905352f7f91STakashi Iwai {
906352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
907352f7f91STakashi Iwai 	if (path) {
908352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
909352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
910352f7f91STakashi Iwai 			chs = 3; /* stereo */
911352f7f91STakashi Iwai 	}
912352f7f91STakashi Iwai 	return chs;
913352f7f91STakashi Iwai }
914352f7f91STakashi Iwai 
915352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
916352f7f91STakashi Iwai 			  struct nid_path *path)
917352f7f91STakashi Iwai {
918352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
919352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
920352f7f91STakashi Iwai }
921352f7f91STakashi Iwai 
922352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
923352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
924352f7f91STakashi Iwai  */
925352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
926352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
927352f7f91STakashi Iwai {
928352f7f91STakashi Iwai 	unsigned int val;
929352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
930352f7f91STakashi Iwai 
931352f7f91STakashi Iwai 	if (!path)
932352f7f91STakashi Iwai 		return 0;
933352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
934352f7f91STakashi Iwai 	if (!val)
935352f7f91STakashi Iwai 		return 0;
936352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
937352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
938352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
939352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
940352f7f91STakashi Iwai 		if (nums > 1) {
941352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
942352f7f91STakashi Iwai 			val |= nums << 19;
943352f7f91STakashi Iwai 		}
944352f7f91STakashi Iwai 	}
945352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
946352f7f91STakashi Iwai }
947352f7f91STakashi Iwai 
948352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
949352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
950352f7f91STakashi Iwai {
951352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
952352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
953352f7f91STakashi Iwai }
954352f7f91STakashi Iwai 
9557eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
956bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
9577eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
9587eebffd3STakashi Iwai {
9597eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9607eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
9617eebffd3STakashi Iwai 
9627eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
9637eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
9647eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
9657eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
9667eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
9677eebffd3STakashi Iwai 	}
968bc2eee29STakashi Iwai }
9697eebffd3STakashi Iwai 
970bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
971bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
972bc2eee29STakashi Iwai {
973bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
9747eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
9757eebffd3STakashi Iwai }
9767eebffd3STakashi Iwai 
977bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
978bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
979bc2eee29STakashi Iwai {
980bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
981bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
982bc2eee29STakashi Iwai }
983bc2eee29STakashi Iwai 
984247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
985247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
986247d85eeSTakashi Iwai {
987247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
988247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
989247d85eeSTakashi Iwai }
990247d85eeSTakashi Iwai 
991352f7f91STakashi Iwai static const char * const channel_name[4] = {
992352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
993352f7f91STakashi Iwai };
994352f7f91STakashi Iwai 
995352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
996247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
997247d85eeSTakashi Iwai 				    int *index, int ctl_type)
998352f7f91STakashi Iwai {
999247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1000352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1001352f7f91STakashi Iwai 
1002352f7f91STakashi Iwai 	*index = 0;
1003352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1004247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1005352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1006352f7f91STakashi Iwai 
1007352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1008352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1009352f7f91STakashi Iwai 	 */
1010352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1011352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1012352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1013352f7f91STakashi Iwai 
1014247d85eeSTakashi Iwai 	/* multi-io channels */
1015247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1016247d85eeSTakashi Iwai 		return channel_name[ch];
1017247d85eeSTakashi Iwai 
1018352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1019352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1020247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1021247d85eeSTakashi Iwai 		 * don't name it as Speaker
1022247d85eeSTakashi Iwai 		 */
1023247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1024247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1025247d85eeSTakashi Iwai 			break;
1026352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1027352f7f91STakashi Iwai 			return "Speaker";
1028352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1029352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1030352f7f91STakashi Iwai 		break;
1031352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1032247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1033247d85eeSTakashi Iwai 		 * don't name it as Headphone
1034247d85eeSTakashi Iwai 		 */
1035247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1036247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1037247d85eeSTakashi Iwai 			break;
1038352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1039352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1040352f7f91STakashi Iwai 			break;
1041352f7f91STakashi Iwai 		*index = ch;
1042352f7f91STakashi Iwai 		return "Headphone";
1043247d85eeSTakashi Iwai 	}
1044247d85eeSTakashi Iwai 
1045247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1046352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
1047352f7f91STakashi Iwai 		return "PCM";
1048247d85eeSTakashi Iwai 
1049352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1050352f7f91STakashi Iwai 		snd_BUG();
1051352f7f91STakashi Iwai 		return "PCM";
1052352f7f91STakashi Iwai 	}
1053352f7f91STakashi Iwai 
1054352f7f91STakashi Iwai 	return channel_name[ch];
1055352f7f91STakashi Iwai }
1056352f7f91STakashi Iwai 
1057352f7f91STakashi Iwai /*
1058352f7f91STakashi Iwai  * Parse output paths
1059352f7f91STakashi Iwai  */
1060352f7f91STakashi Iwai 
1061352f7f91STakashi Iwai /* badness definition */
1062352f7f91STakashi Iwai enum {
1063352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1064352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1065352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1066352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1067352f7f91STakashi Iwai 	/* No possible multi-ios */
10681d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1069352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1070352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1071352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1072352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1073352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1074352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
107555a63d4dSTakashi Iwai 	/* No independent HP possible */
1076bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1077352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1078352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1079352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1080352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1081352f7f91STakashi Iwai 	/* Volume widget is shared */
1082352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1083352f7f91STakashi Iwai };
1084352f7f91STakashi Iwai 
10850e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1086352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1087352f7f91STakashi Iwai  *
1088352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1089352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1090352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1091352f7f91STakashi Iwai  */
10920e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1093352f7f91STakashi Iwai {
1094352f7f91STakashi Iwai 	hda_nid_t nid;
1095352f7f91STakashi Iwai 	unsigned int val;
1096352f7f91STakashi Iwai 	int badness = 0;
1097352f7f91STakashi Iwai 
1098352f7f91STakashi Iwai 	if (!path)
1099352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
11000e614dd0STakashi Iwai 
11010e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
11020e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
11030e614dd0STakashi Iwai 		return 0; /* already evaluated */
11040e614dd0STakashi Iwai 
1105352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1106352f7f91STakashi Iwai 	if (nid) {
1107352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1108352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1109352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1110352f7f91STakashi Iwai 		else
1111352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1112352f7f91STakashi Iwai 	} else
1113352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1114352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1115352f7f91STakashi Iwai 	if (nid) {
1116352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1117352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1118352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1119352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1120352f7f91STakashi Iwai 		else
1121352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1122352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1123352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1124352f7f91STakashi Iwai 		else
1125352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1126352f7f91STakashi Iwai 	} else
1127352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1128352f7f91STakashi Iwai 	return badness;
1129352f7f91STakashi Iwai }
1130352f7f91STakashi Iwai 
113198bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1132352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1133352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1134352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1135352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1136352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1137352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1138352f7f91STakashi Iwai };
113998bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_main_out_badness);
1140352f7f91STakashi Iwai 
114198bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1142352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1143352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1144352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1145352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1146352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1147352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1148352f7f91STakashi Iwai };
114998bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_extra_out_badness);
1150352f7f91STakashi Iwai 
11517385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
11527385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
11537385df61STakashi Iwai {
11547385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
11557385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
11567385df61STakashi Iwai 
11577385df61STakashi Iwai 	if (cfg->line_outs > idx)
11587385df61STakashi Iwai 		return spec->private_dac_nids[idx];
11597385df61STakashi Iwai 	idx -= cfg->line_outs;
11607385df61STakashi Iwai 	if (spec->multi_ios > idx)
11617385df61STakashi Iwai 		return spec->multi_io[idx].dac;
11627385df61STakashi Iwai 	return 0;
11637385df61STakashi Iwai }
11647385df61STakashi Iwai 
11657385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
11667385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
11677385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
11687385df61STakashi Iwai {
11697385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
11707385df61STakashi Iwai }
11717385df61STakashi Iwai 
1172352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1173352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1174352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1175196c1766STakashi Iwai 			   int *path_idx,
1176352f7f91STakashi Iwai 			   const struct badness_table *bad)
1177352f7f91STakashi Iwai {
1178352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1179352f7f91STakashi Iwai 	int i, j;
1180352f7f91STakashi Iwai 	int badness = 0;
1181352f7f91STakashi Iwai 	hda_nid_t dac;
1182352f7f91STakashi Iwai 
1183352f7f91STakashi Iwai 	if (!num_outs)
1184352f7f91STakashi Iwai 		return 0;
1185352f7f91STakashi Iwai 
1186352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
11870c8c0f56STakashi Iwai 		struct nid_path *path;
1188352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
11891e0b5286STakashi Iwai 
11900e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
11910e614dd0STakashi Iwai 		if (path) {
11920e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
11931e0b5286STakashi Iwai 			continue;
11941e0b5286STakashi Iwai 		}
11951e0b5286STakashi Iwai 
1196352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1197352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1198980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1199352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1200352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1201352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1202352f7f91STakashi Iwai 					dacs[j] = 0;
1203980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1204196c1766STakashi Iwai 					path_idx[j] = 0;
1205352f7f91STakashi Iwai 					break;
1206352f7f91STakashi Iwai 				}
1207352f7f91STakashi Iwai 			}
1208352f7f91STakashi Iwai 		}
1209352f7f91STakashi Iwai 		dac = dacs[i];
1210352f7f91STakashi Iwai 		if (!dac) {
12117385df61STakashi Iwai 			if (num_outs > 2)
12127385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
12137385df61STakashi Iwai 			if (!dac)
12147385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
12157385df61STakashi Iwai 			if (!dac)
12167385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1217352f7f91STakashi Iwai 			if (dac) {
1218352f7f91STakashi Iwai 				if (!i)
1219352f7f91STakashi Iwai 					badness += bad->shared_primary;
1220352f7f91STakashi Iwai 				else if (i == 1)
1221352f7f91STakashi Iwai 					badness += bad->shared_surr;
1222352f7f91STakashi Iwai 				else
1223352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1224352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1225352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1226352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1227352f7f91STakashi Iwai 			} else if (!i)
1228352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1229352f7f91STakashi Iwai 			else
1230352f7f91STakashi Iwai 				badness += bad->no_dac;
1231352f7f91STakashi Iwai 		}
12321fa335b0STakashi Iwai 		if (!dac)
12331fa335b0STakashi Iwai 			continue;
12343ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1235117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1236b3a8c745STakashi Iwai 			/* try with aamix */
12373ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1238b3a8c745STakashi Iwai 		}
12391fa335b0STakashi Iwai 		if (!path) {
1240352f7f91STakashi Iwai 			dac = dacs[i] = 0;
12411fa335b0STakashi Iwai 			badness += bad->no_dac;
12421fa335b0STakashi Iwai 		} else {
1243a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1244e1284af7STakashi Iwai 			path->active = true;
1245196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
12460e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1247e1284af7STakashi Iwai 		}
1248352f7f91STakashi Iwai 	}
1249352f7f91STakashi Iwai 
1250352f7f91STakashi Iwai 	return badness;
1251352f7f91STakashi Iwai }
1252352f7f91STakashi Iwai 
1253352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1254352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1255352f7f91STakashi Iwai {
1256352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1257352f7f91STakashi Iwai 	int i;
1258352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1259352f7f91STakashi Iwai 
1260352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1261352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1262352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1263352f7f91STakashi Iwai 			continue;
1264352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1265352f7f91STakashi Iwai 			if (nid_found)
1266352f7f91STakashi Iwai 				return 0;
1267352f7f91STakashi Iwai 			nid_found = nid;
1268352f7f91STakashi Iwai 		}
1269352f7f91STakashi Iwai 	}
1270352f7f91STakashi Iwai 	return nid_found;
1271352f7f91STakashi Iwai }
1272352f7f91STakashi Iwai 
1273352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1274352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1275352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1276352f7f91STakashi Iwai {
1277352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1278352f7f91STakashi Iwai 
1279352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1280352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1281352f7f91STakashi Iwai 		return false;
1282352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1283352f7f91STakashi Iwai 		return false;
1284352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1285352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1286352f7f91STakashi Iwai 		return false;
1287352f7f91STakashi Iwai 	return true;
1288352f7f91STakashi Iwai }
1289352f7f91STakashi Iwai 
1290e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1291e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1292e22aab7dSTakashi Iwai {
1293e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1294e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1295e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1296e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1297e22aab7dSTakashi Iwai 	int type, i;
1298e22aab7dSTakashi Iwai 	int num_pins = 0;
1299e22aab7dSTakashi Iwai 
1300e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1301e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1302e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1303e22aab7dSTakashi Iwai 				continue;
1304e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1305e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1306e22aab7dSTakashi Iwai 				num_pins++;
1307e22aab7dSTakashi Iwai 		}
1308e22aab7dSTakashi Iwai 	}
1309e22aab7dSTakashi Iwai 	return num_pins;
1310e22aab7dSTakashi Iwai }
1311e22aab7dSTakashi Iwai 
1312352f7f91STakashi Iwai /*
1313352f7f91STakashi Iwai  * multi-io helper
1314352f7f91STakashi Iwai  *
1315352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1316352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1317352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1318352f7f91STakashi Iwai  * the badness value.
1319352f7f91STakashi Iwai  */
1320352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1321352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1322e22aab7dSTakashi Iwai 			  bool hardwired)
1323352f7f91STakashi Iwai {
1324352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1325352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1326e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1327352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1328352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1329352f7f91STakashi Iwai 	int badness = 0;
13300e614dd0STakashi Iwai 	struct nid_path *path;
1331352f7f91STakashi Iwai 
1332352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1333352f7f91STakashi Iwai 	if (old_pins >= 2)
1334352f7f91STakashi Iwai 		goto end_fill;
1335352f7f91STakashi Iwai 
1336e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1337352f7f91STakashi Iwai 	if (num_pins < 2)
1338352f7f91STakashi Iwai 		goto end_fill;
1339352f7f91STakashi Iwai 
1340352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1341352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1342352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1343352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1344352f7f91STakashi Iwai 
1345352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1346352f7f91STakashi Iwai 				continue;
1347352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1348352f7f91STakashi Iwai 				continue;
1349352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1350352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1351352f7f91STakashi Iwai 					break;
1352352f7f91STakashi Iwai 			}
1353352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1354352f7f91STakashi Iwai 				continue;
1355352f7f91STakashi Iwai 
1356352f7f91STakashi Iwai 			if (hardwired)
1357352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1358352f7f91STakashi Iwai 			else if (!dac)
1359352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1360352f7f91STakashi Iwai 			if (!dac) {
1361352f7f91STakashi Iwai 				badness++;
1362352f7f91STakashi Iwai 				continue;
1363352f7f91STakashi Iwai 			}
13643ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
13653ca529d3STakashi Iwai 						    -spec->mixer_nid);
13660c8c0f56STakashi Iwai 			if (!path) {
1367352f7f91STakashi Iwai 				badness++;
1368352f7f91STakashi Iwai 				continue;
1369352f7f91STakashi Iwai 			}
1370a769409cSTakashi Iwai 			/* print_nid_path("multiio", path); */
1371352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1372352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1373196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1374196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1375352f7f91STakashi Iwai 			spec->multi_ios++;
1376352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1377352f7f91STakashi Iwai 				break;
1378352f7f91STakashi Iwai 		}
1379352f7f91STakashi Iwai 	}
1380352f7f91STakashi Iwai  end_fill:
1381352f7f91STakashi Iwai 	if (badness)
1382352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1383352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1384352f7f91STakashi Iwai 		if (hardwired)
1385352f7f91STakashi Iwai 			return 1; /* nothing found */
1386352f7f91STakashi Iwai 		else
1387352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1388352f7f91STakashi Iwai 	}
1389352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1390352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1391352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1392352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1393352f7f91STakashi Iwai 		return badness;
1394352f7f91STakashi Iwai 	}
1395352f7f91STakashi Iwai 
1396352f7f91STakashi Iwai 	/* assign volume and mute controls */
13970e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
13980e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
13990e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
14000e614dd0STakashi Iwai 	}
1401352f7f91STakashi Iwai 
1402352f7f91STakashi Iwai 	return badness;
1403352f7f91STakashi Iwai }
1404352f7f91STakashi Iwai 
1405352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1406352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1407196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1408352f7f91STakashi Iwai {
1409b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1410352f7f91STakashi Iwai 	int i;
1411352f7f91STakashi Iwai 	bool found = false;
1412352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
14130c8c0f56STakashi Iwai 		struct nid_path *path;
1414352f7f91STakashi Iwai 		hda_nid_t dac;
1415352f7f91STakashi Iwai 		if (dacs[i])
1416352f7f91STakashi Iwai 			continue;
1417352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1418352f7f91STakashi Iwai 		if (!dac)
1419352f7f91STakashi Iwai 			continue;
14203ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
14213ca529d3STakashi Iwai 					    -spec->mixer_nid);
1422117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
14233ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
14240c8c0f56STakashi Iwai 		if (path) {
1425352f7f91STakashi Iwai 			dacs[i] = dac;
1426352f7f91STakashi Iwai 			found = true;
1427a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1428e1284af7STakashi Iwai 			path->active = true;
1429196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1430352f7f91STakashi Iwai 		}
1431352f7f91STakashi Iwai 	}
1432352f7f91STakashi Iwai 	return found;
1433352f7f91STakashi Iwai }
1434352f7f91STakashi Iwai 
1435c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1436c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1437c30aa7b2STakashi Iwai {
14383ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1439c30aa7b2STakashi Iwai 	struct nid_path *path;
14405ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1441c30aa7b2STakashi Iwai 
1442c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
14433ca529d3STakashi Iwai 	if (!path || !path->depth ||
14443ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1445c30aa7b2STakashi Iwai 		return 0;
14465ead56f2STakashi Iwai 	path_dac = path->path[0];
14475ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1448f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1449f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1450f87498b6STakashi Iwai 	if (!path) {
14515ead56f2STakashi Iwai 		if (dac != path_dac)
14525ead56f2STakashi Iwai 			dac = path_dac;
1453f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1454f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1455f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1456f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
14575ead56f2STakashi Iwai 		else
14585ead56f2STakashi Iwai 			dac = 0;
1459f87498b6STakashi Iwai 		if (dac)
1460f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
14613ca529d3STakashi Iwai 						    spec->mixer_nid);
1462f87498b6STakashi Iwai 	}
1463c30aa7b2STakashi Iwai 	if (!path)
1464c30aa7b2STakashi Iwai 		return 0;
1465a769409cSTakashi Iwai 	/* print_nid_path("output-aamix", path); */
1466c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1467c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1468c30aa7b2STakashi Iwai }
1469c30aa7b2STakashi Iwai 
147055a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
147155a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
147255a63d4dSTakashi Iwai {
147355a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
147455a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
147555a63d4dSTakashi Iwai 	struct nid_path *path;
147655a63d4dSTakashi Iwai 	int i, idx;
147755a63d4dSTakashi Iwai 
147855a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
147955a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
148055a63d4dSTakashi Iwai 	else
148155a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
148255a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
148355a63d4dSTakashi Iwai 	if (!path)
148455a63d4dSTakashi Iwai 		return false;
148555a63d4dSTakashi Iwai 
148655a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
148755a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
148855a63d4dSTakashi Iwai 		return true;
148955a63d4dSTakashi Iwai 
149055a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
149155a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
149255a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
149355a63d4dSTakashi Iwai 			break;
149455a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
149555a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
149655a63d4dSTakashi Iwai 			return false;
149755a63d4dSTakashi Iwai 	}
149855a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
149955a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
150055a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
150155a63d4dSTakashi Iwai 			return false;
150255a63d4dSTakashi Iwai 	}
150355a63d4dSTakashi Iwai 
150455a63d4dSTakashi Iwai 	return true;
150555a63d4dSTakashi Iwai }
150655a63d4dSTakashi Iwai 
1507a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1508a07a949bSTakashi Iwai  * shared dac pointed by the paths
1509a07a949bSTakashi Iwai  */
1510a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1511a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1512a07a949bSTakashi Iwai {
1513a07a949bSTakashi Iwai 	struct nid_path *path;
1514a07a949bSTakashi Iwai 	int i;
1515a07a949bSTakashi Iwai 
1516a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1517a07a949bSTakashi Iwai 		if (dacs[i])
1518a07a949bSTakashi Iwai 			continue;
1519a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1520a07a949bSTakashi Iwai 		if (!path)
1521a07a949bSTakashi Iwai 			continue;
1522a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1523a07a949bSTakashi Iwai 	}
1524a07a949bSTakashi Iwai }
1525a07a949bSTakashi Iwai 
1526352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1527352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1528352f7f91STakashi Iwai 			      bool fill_hardwired,
1529352f7f91STakashi Iwai 			      bool fill_mio_first)
1530352f7f91STakashi Iwai {
1531352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1532352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1533352f7f91STakashi Iwai 	int i, err, badness;
1534352f7f91STakashi Iwai 
1535352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1536352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1537352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1538352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1539352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1540352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1541352f7f91STakashi Iwai 	spec->multi_ios = 0;
1542352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1543cd5be3f9STakashi Iwai 
1544cd5be3f9STakashi Iwai 	/* clear path indices */
1545cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1546cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1547cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1548cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1549cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1550c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1551cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1552cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1553cd5be3f9STakashi Iwai 
1554352f7f91STakashi Iwai 	badness = 0;
1555352f7f91STakashi Iwai 
1556352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1557352f7f91STakashi Iwai 	if (fill_hardwired) {
1558352f7f91STakashi Iwai 		bool mapped;
1559352f7f91STakashi Iwai 		do {
1560352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1561352f7f91STakashi Iwai 					     cfg->line_out_pins,
1562196c1766STakashi Iwai 					     spec->private_dac_nids,
1563196c1766STakashi Iwai 					     spec->out_paths);
1564352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1565352f7f91STakashi Iwai 					      cfg->hp_pins,
1566196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1567196c1766STakashi Iwai 					      spec->hp_paths);
1568352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1569352f7f91STakashi Iwai 					      cfg->speaker_pins,
1570196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1571196c1766STakashi Iwai 					      spec->speaker_paths);
1572da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1573da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1574352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1575e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1576352f7f91STakashi Iwai 				if (!err)
1577352f7f91STakashi Iwai 					mapped = true;
1578352f7f91STakashi Iwai 			}
1579352f7f91STakashi Iwai 		} while (mapped);
1580352f7f91STakashi Iwai 	}
1581352f7f91STakashi Iwai 
1582352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1583196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
158498bd1115STakashi Iwai 				   spec->main_out_badness);
1585352f7f91STakashi Iwai 
1586da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1587352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1588352f7f91STakashi Iwai 		/* try to fill multi-io first */
1589e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1590352f7f91STakashi Iwai 		if (err < 0)
1591352f7f91STakashi Iwai 			return err;
1592352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1593352f7f91STakashi Iwai 	}
1594352f7f91STakashi Iwai 
1595352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1596352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1597352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1598196c1766STakashi Iwai 				      spec->hp_paths,
159998bd1115STakashi Iwai 				      spec->extra_out_badness);
1600352f7f91STakashi Iwai 		if (err < 0)
1601352f7f91STakashi Iwai 			return err;
1602352f7f91STakashi Iwai 		badness += err;
1603352f7f91STakashi Iwai 	}
1604352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1605352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1606352f7f91STakashi Iwai 				      cfg->speaker_pins,
1607352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1608196c1766STakashi Iwai 				      spec->speaker_paths,
160998bd1115STakashi Iwai 				      spec->extra_out_badness);
1610352f7f91STakashi Iwai 		if (err < 0)
1611352f7f91STakashi Iwai 			return err;
1612352f7f91STakashi Iwai 		badness += err;
1613352f7f91STakashi Iwai 	}
1614da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1615da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1616e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1617352f7f91STakashi Iwai 		if (err < 0)
1618352f7f91STakashi Iwai 			return err;
1619352f7f91STakashi Iwai 		badness += err;
1620352f7f91STakashi Iwai 	}
1621e22aab7dSTakashi Iwai 
1622c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1623c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1624c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1625c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1626c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1627c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1628c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1629c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1630c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1631c30aa7b2STakashi Iwai 	}
1632c30aa7b2STakashi Iwai 
1633da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1634da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1635e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1636e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1637352f7f91STakashi Iwai 
1638a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1639a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1640a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1641a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1642a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1643a07a949bSTakashi Iwai 		else {
1644a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1645a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1646a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1647a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1648a07a949bSTakashi Iwai 		}
1649a07a949bSTakashi Iwai 	}
1650a07a949bSTakashi Iwai 
1651a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1652c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1653a07a949bSTakashi Iwai 
1654352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1655352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1656352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1657352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1658352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1659352f7f91STakashi Iwai 		spec->multi_ios = 0;
1660352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1661352f7f91STakashi Iwai 	}
1662352f7f91STakashi Iwai 
166355a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
166455a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
166555a63d4dSTakashi Iwai 
1666a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1667a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1668a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1669a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1670a07a949bSTakashi Iwai 				   spec->hp_paths);
1671a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1672a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1673a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1674a07a949bSTakashi Iwai 				   spec->speaker_paths);
1675a07a949bSTakashi Iwai 
1676352f7f91STakashi Iwai 	return badness;
1677352f7f91STakashi Iwai }
1678352f7f91STakashi Iwai 
1679352f7f91STakashi Iwai #define DEBUG_BADNESS
1680352f7f91STakashi Iwai 
1681352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1682352f7f91STakashi Iwai #define debug_badness	snd_printdd
1683352f7f91STakashi Iwai #else
1684352f7f91STakashi Iwai #define debug_badness(...)
1685352f7f91STakashi Iwai #endif
1686352f7f91STakashi Iwai 
1687a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1688a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1689a769409cSTakashi Iwai 				      const char *pfx, int idx)
1690352f7f91STakashi Iwai {
1691a769409cSTakashi Iwai 	struct nid_path *path;
1692a769409cSTakashi Iwai 
1693a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1694a769409cSTakashi Iwai 	if (path)
1695a769409cSTakashi Iwai 		print_nid_path(pfx, path);
1696a769409cSTakashi Iwai }
1697a769409cSTakashi Iwai 
1698a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1699a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1700a769409cSTakashi Iwai {
1701a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1702a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1703a769409cSTakashi Iwai 	int i;
1704a769409cSTakashi Iwai 
1705a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1706352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1707708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1708352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1709352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1710352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1711a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1712a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1713a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1714a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1715352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1716352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1717352f7f91STakashi Iwai 			      spec->multi_ios,
1718352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1719352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1720a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1721a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1722a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1723a769409cSTakashi Iwai 	if (cfg->hp_outs)
1724352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1725352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1726708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1727352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1728352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1729352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1730352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1731a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1732a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1733a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1734352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1735352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1736352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1737352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1738352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1739352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1740352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1741a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1742a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1743a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1744a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1745352f7f91STakashi Iwai }
1746a769409cSTakashi Iwai #else
1747a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1748a769409cSTakashi Iwai #endif
1749352f7f91STakashi Iwai 
1750352f7f91STakashi Iwai /* find all available DACs of the codec */
1751352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1752352f7f91STakashi Iwai {
1753352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1754352f7f91STakashi Iwai 	int i;
1755352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1756352f7f91STakashi Iwai 
1757352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1758352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1759352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1760352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1761352f7f91STakashi Iwai 			continue;
1762352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1763352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1764352f7f91STakashi Iwai 			break;
1765352f7f91STakashi Iwai 		}
1766352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1767352f7f91STakashi Iwai 	}
1768352f7f91STakashi Iwai }
1769352f7f91STakashi Iwai 
1770352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1771352f7f91STakashi Iwai {
1772352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1773352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1774352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
17759314a581STakashi Iwai 	unsigned int val;
1776352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1777352f7f91STakashi Iwai 	int badness;
1778352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1779352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1780352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1781352f7f91STakashi Iwai 
1782352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1783352f7f91STakashi Iwai 	if (!best_cfg)
1784352f7f91STakashi Iwai 		return -ENOMEM;
1785352f7f91STakashi Iwai 	*best_cfg = *cfg;
1786352f7f91STakashi Iwai 
1787352f7f91STakashi Iwai 	for (;;) {
1788352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1789352f7f91STakashi Iwai 					     fill_mio_first);
1790352f7f91STakashi Iwai 		if (badness < 0) {
1791352f7f91STakashi Iwai 			kfree(best_cfg);
1792352f7f91STakashi Iwai 			return badness;
1793352f7f91STakashi Iwai 		}
1794352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1795352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1796352f7f91STakashi Iwai 			      badness);
1797a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1798352f7f91STakashi Iwai 		if (badness < best_badness) {
1799352f7f91STakashi Iwai 			best_badness = badness;
1800352f7f91STakashi Iwai 			*best_cfg = *cfg;
1801352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1802352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1803352f7f91STakashi Iwai 		}
1804352f7f91STakashi Iwai 		if (!badness)
1805352f7f91STakashi Iwai 			break;
1806352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1807352f7f91STakashi Iwai 		if (!fill_mio_first)
1808352f7f91STakashi Iwai 			continue;
1809352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1810352f7f91STakashi Iwai 		if (!fill_hardwired)
1811352f7f91STakashi Iwai 			continue;
1812352f7f91STakashi Iwai 		if (hp_spk_swapped)
1813352f7f91STakashi Iwai 			break;
1814352f7f91STakashi Iwai 		hp_spk_swapped = true;
1815352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1816352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1817352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1818352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1819352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1820352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1821352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1822352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1823352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1824352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1825352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1826352f7f91STakashi Iwai 			fill_hardwired = true;
1827352f7f91STakashi Iwai 			continue;
1828352f7f91STakashi Iwai 		}
1829352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1830352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1831352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1832352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1833352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1834352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1835352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1836352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1837352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1838352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1839352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1840352f7f91STakashi Iwai 			fill_hardwired = true;
1841352f7f91STakashi Iwai 			continue;
1842352f7f91STakashi Iwai 		}
1843352f7f91STakashi Iwai 		break;
1844352f7f91STakashi Iwai 	}
1845352f7f91STakashi Iwai 
1846352f7f91STakashi Iwai 	if (badness) {
18470c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1848352f7f91STakashi Iwai 		*cfg = *best_cfg;
1849352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1850352f7f91STakashi Iwai 	}
1851352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1852352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1853a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
1854352f7f91STakashi Iwai 
1855352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1856352f7f91STakashi Iwai 		struct nid_path *path;
1857196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1858352f7f91STakashi Iwai 		if (path)
1859352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
18607a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
18617a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
18627a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1863352f7f91STakashi Iwai 	}
1864352f7f91STakashi Iwai 
18659314a581STakashi Iwai 	/* set initial pinctl targets */
18669314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
18679314a581STakashi Iwai 		val = PIN_HP;
18689314a581STakashi Iwai 	else
18699314a581STakashi Iwai 		val = PIN_OUT;
18709314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
18719314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
18729314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
18739314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
18749314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
18759314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
18769314a581STakashi Iwai 				cfg->speaker_pins, val);
18779314a581STakashi Iwai 	}
18789314a581STakashi Iwai 
187955a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
188055a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
188155a63d4dSTakashi Iwai 		spec->indep_hp = 0;
188255a63d4dSTakashi Iwai 
1883352f7f91STakashi Iwai 	kfree(best_cfg);
1884352f7f91STakashi Iwai 	return 0;
1885352f7f91STakashi Iwai }
1886352f7f91STakashi Iwai 
1887352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1888352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1889352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1890352f7f91STakashi Iwai {
1891352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1892352f7f91STakashi Iwai 	int i, err, noutputs;
1893352f7f91STakashi Iwai 
1894352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1895352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1896352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1897352f7f91STakashi Iwai 
1898352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1899352f7f91STakashi Iwai 		const char *name;
1900352f7f91STakashi Iwai 		int index;
1901352f7f91STakashi Iwai 		struct nid_path *path;
1902352f7f91STakashi Iwai 
1903196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1904352f7f91STakashi Iwai 		if (!path)
1905352f7f91STakashi Iwai 			continue;
1906247d85eeSTakashi Iwai 
1907247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1908352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1909352f7f91STakashi Iwai 			/* Center/LFE */
1910352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1911352f7f91STakashi Iwai 			if (err < 0)
1912352f7f91STakashi Iwai 				return err;
1913352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1914352f7f91STakashi Iwai 			if (err < 0)
1915352f7f91STakashi Iwai 				return err;
1916247d85eeSTakashi Iwai 		} else {
1917247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1918247d85eeSTakashi Iwai 			if (err < 0)
1919247d85eeSTakashi Iwai 				return err;
1920247d85eeSTakashi Iwai 		}
1921247d85eeSTakashi Iwai 
1922247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1923247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1924352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1925352f7f91STakashi Iwai 			if (err < 0)
1926352f7f91STakashi Iwai 				return err;
1927352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1928352f7f91STakashi Iwai 			if (err < 0)
1929352f7f91STakashi Iwai 				return err;
1930352f7f91STakashi Iwai 		} else {
1931352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1932352f7f91STakashi Iwai 			if (err < 0)
1933352f7f91STakashi Iwai 				return err;
1934352f7f91STakashi Iwai 		}
1935352f7f91STakashi Iwai 	}
1936352f7f91STakashi Iwai 	return 0;
1937352f7f91STakashi Iwai }
1938352f7f91STakashi Iwai 
1939c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1940196c1766STakashi Iwai 			    const char *pfx, int cidx)
1941352f7f91STakashi Iwai {
1942352f7f91STakashi Iwai 	struct nid_path *path;
1943352f7f91STakashi Iwai 	int err;
1944352f7f91STakashi Iwai 
1945196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1946352f7f91STakashi Iwai 	if (!path)
1947352f7f91STakashi Iwai 		return 0;
1948352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1949352f7f91STakashi Iwai 	if (err < 0)
1950352f7f91STakashi Iwai 		return err;
1951352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1952352f7f91STakashi Iwai 	if (err < 0)
1953352f7f91STakashi Iwai 		return err;
1954352f7f91STakashi Iwai 	return 0;
1955352f7f91STakashi Iwai }
1956352f7f91STakashi Iwai 
1957352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1958352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1959196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1960352f7f91STakashi Iwai {
1961c2c80383STakashi Iwai 	int i;
1962352f7f91STakashi Iwai 
1963352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1964c2c80383STakashi Iwai 		const char *name;
1965975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1966c2c80383STakashi Iwai 		int err, idx = 0;
1967c2c80383STakashi Iwai 
1968c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1969c2c80383STakashi Iwai 			name = "Bass Speaker";
1970c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1971c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1972352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1973c2c80383STakashi Iwai 			name = tmp;
1974352f7f91STakashi Iwai 		} else {
1975c2c80383STakashi Iwai 			name = pfx;
1976c2c80383STakashi Iwai 			idx = i;
1977352f7f91STakashi Iwai 		}
1978c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1979352f7f91STakashi Iwai 		if (err < 0)
1980352f7f91STakashi Iwai 			return err;
1981352f7f91STakashi Iwai 	}
1982352f7f91STakashi Iwai 	return 0;
1983352f7f91STakashi Iwai }
1984352f7f91STakashi Iwai 
1985352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1986352f7f91STakashi Iwai {
1987352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1988352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1989196c1766STakashi Iwai 				 spec->hp_paths,
1990352f7f91STakashi Iwai 				 "Headphone");
1991352f7f91STakashi Iwai }
1992352f7f91STakashi Iwai 
1993352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1994352f7f91STakashi Iwai {
1995352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1996352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1997196c1766STakashi Iwai 				 spec->speaker_paths,
1998352f7f91STakashi Iwai 				 "Speaker");
1999352f7f91STakashi Iwai }
2000352f7f91STakashi Iwai 
2001352f7f91STakashi Iwai /*
200238cf6f1aSTakashi Iwai  * independent HP controls
200338cf6f1aSTakashi Iwai  */
200438cf6f1aSTakashi Iwai 
2005963afde9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
200638cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
200738cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
200838cf6f1aSTakashi Iwai {
200938cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
201038cf6f1aSTakashi Iwai }
201138cf6f1aSTakashi Iwai 
201238cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
201338cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
201438cf6f1aSTakashi Iwai {
201538cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
201638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
201738cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
201838cf6f1aSTakashi Iwai 	return 0;
201938cf6f1aSTakashi Iwai }
202038cf6f1aSTakashi Iwai 
2021a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2022a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2023a1e908edSTakashi Iwai 			       int out_type);
2024a1e908edSTakashi Iwai 
202538cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
202638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
202738cf6f1aSTakashi Iwai {
202838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
202938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
203038cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
203138cf6f1aSTakashi Iwai 	int ret = 0;
203238cf6f1aSTakashi Iwai 
203338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
203438cf6f1aSTakashi Iwai 	if (spec->active_streams) {
203538cf6f1aSTakashi Iwai 		ret = -EBUSY;
203638cf6f1aSTakashi Iwai 		goto unlock;
203738cf6f1aSTakashi Iwai 	}
203838cf6f1aSTakashi Iwai 
203938cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2040a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2041a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2042a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2043a1e908edSTakashi Iwai 		else
2044a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2045a1e908edSTakashi Iwai 
2046a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2047a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2048a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2049a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2050a1e908edSTakashi Iwai 						   spec->out_paths[0],
2051a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2052a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2053a1e908edSTakashi Iwai 			else
2054a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2055a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2056a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2057a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2058a1e908edSTakashi Iwai 		}
2059a1e908edSTakashi Iwai 
206038cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
206138cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2062a1e908edSTakashi Iwai 			*dacp = 0;
206338cf6f1aSTakashi Iwai 		else
2064a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
206592603c59STakashi Iwai 
2066963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
206738cf6f1aSTakashi Iwai 		ret = 1;
206838cf6f1aSTakashi Iwai 	}
206938cf6f1aSTakashi Iwai  unlock:
207038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
207138cf6f1aSTakashi Iwai 	return ret;
207238cf6f1aSTakashi Iwai }
207338cf6f1aSTakashi Iwai 
207438cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
207538cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
207638cf6f1aSTakashi Iwai 	.name = "Independent HP",
207738cf6f1aSTakashi Iwai 	.info = indep_hp_info,
207838cf6f1aSTakashi Iwai 	.get = indep_hp_get,
207938cf6f1aSTakashi Iwai 	.put = indep_hp_put,
208038cf6f1aSTakashi Iwai };
208138cf6f1aSTakashi Iwai 
208238cf6f1aSTakashi Iwai 
208338cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
208438cf6f1aSTakashi Iwai {
208538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2086a1e908edSTakashi Iwai 	hda_nid_t dac;
208738cf6f1aSTakashi Iwai 
208838cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
208938cf6f1aSTakashi Iwai 		return 0;
2090a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2091a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2092a1e908edSTakashi Iwai 	else
2093a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2094a1e908edSTakashi Iwai 	if (!dac) {
209538cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
209638cf6f1aSTakashi Iwai 		return 0;
209738cf6f1aSTakashi Iwai 	}
209838cf6f1aSTakashi Iwai 
209938cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2100a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
210138cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
210238cf6f1aSTakashi Iwai 		return -ENOMEM;
210338cf6f1aSTakashi Iwai 	return 0;
210438cf6f1aSTakashi Iwai }
210538cf6f1aSTakashi Iwai 
210638cf6f1aSTakashi Iwai /*
2107352f7f91STakashi Iwai  * channel mode enum control
2108352f7f91STakashi Iwai  */
2109352f7f91STakashi Iwai 
2110352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2111352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2112352f7f91STakashi Iwai {
2113352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2114352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2115a07a949bSTakashi Iwai 	int chs;
2116352f7f91STakashi Iwai 
2117352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2118352f7f91STakashi Iwai 	uinfo->count = 1;
2119352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2120352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2121352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2122a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2123a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2124352f7f91STakashi Iwai 	return 0;
2125352f7f91STakashi Iwai }
2126352f7f91STakashi Iwai 
2127352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2128352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2129352f7f91STakashi Iwai {
2130352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2131352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2132a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2133a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2134352f7f91STakashi Iwai 	return 0;
2135352f7f91STakashi Iwai }
2136352f7f91STakashi Iwai 
2137196c1766STakashi Iwai static inline struct nid_path *
2138196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2139196c1766STakashi Iwai {
2140196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2141196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2142196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2143196c1766STakashi Iwai }
2144196c1766STakashi Iwai 
2145a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2146a5cc2509STakashi Iwai 
214765033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
214865033cc8STakashi Iwai  * used for output paths
214965033cc8STakashi Iwai  */
215065033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
215165033cc8STakashi Iwai {
215265033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
215365033cc8STakashi Iwai }
215465033cc8STakashi Iwai 
2155352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2156352f7f91STakashi Iwai {
2157352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2158352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2159352f7f91STakashi Iwai 	struct nid_path *path;
2160352f7f91STakashi Iwai 
2161196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2162352f7f91STakashi Iwai 	if (!path)
2163352f7f91STakashi Iwai 		return -EINVAL;
2164352f7f91STakashi Iwai 
2165352f7f91STakashi Iwai 	if (path->active == output)
2166352f7f91STakashi Iwai 		return 0;
2167352f7f91STakashi Iwai 
2168352f7f91STakashi Iwai 	if (output) {
21692c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
217065033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2171d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2172352f7f91STakashi Iwai 	} else {
2173d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
217465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
21752c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
217655196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2177352f7f91STakashi Iwai 	}
2178a365fed9STakashi Iwai 
2179a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2180a5cc2509STakashi Iwai 	update_automute_all(codec);
2181a365fed9STakashi Iwai 
2182352f7f91STakashi Iwai 	return 0;
2183352f7f91STakashi Iwai }
2184352f7f91STakashi Iwai 
2185352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2186352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2187352f7f91STakashi Iwai {
2188352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2189352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2190352f7f91STakashi Iwai 	int i, ch;
2191352f7f91STakashi Iwai 
2192352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2193352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2194352f7f91STakashi Iwai 		return -EINVAL;
2195a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2196352f7f91STakashi Iwai 		return 0;
2197a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2198352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2199352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2200352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2201352f7f91STakashi Iwai 					  spec->const_channel_count);
2202352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2203352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2204352f7f91STakashi Iwai 	return 1;
2205352f7f91STakashi Iwai }
2206352f7f91STakashi Iwai 
2207352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2208352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2209352f7f91STakashi Iwai 	.name = "Channel Mode",
2210352f7f91STakashi Iwai 	.info = ch_mode_info,
2211352f7f91STakashi Iwai 	.get = ch_mode_get,
2212352f7f91STakashi Iwai 	.put = ch_mode_put,
2213352f7f91STakashi Iwai };
2214352f7f91STakashi Iwai 
2215352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2216352f7f91STakashi Iwai {
2217352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2218352f7f91STakashi Iwai 
2219352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
222012c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2221352f7f91STakashi Iwai 			return -ENOMEM;
2222352f7f91STakashi Iwai 	}
2223352f7f91STakashi Iwai 	return 0;
2224352f7f91STakashi Iwai }
2225352f7f91STakashi Iwai 
2226352f7f91STakashi Iwai /*
2227c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2228c30aa7b2STakashi Iwai  */
2229c30aa7b2STakashi Iwai 
2230c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2231c30aa7b2STakashi Iwai 
2232c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2233c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2234c30aa7b2STakashi Iwai {
2235c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2236c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2237c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2238c30aa7b2STakashi Iwai 	return 0;
2239c30aa7b2STakashi Iwai }
2240c30aa7b2STakashi Iwai 
2241c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2242a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2243a1e908edSTakashi Iwai 			       int out_type)
2244c30aa7b2STakashi Iwai {
2245a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2246c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2247c30aa7b2STakashi Iwai 
2248c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2249c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2250c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2251c30aa7b2STakashi Iwai 		return;
2252a1e908edSTakashi Iwai 
2253a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2254a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2255a1e908edSTakashi Iwai 	 */
2256a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2257a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2258a1e908edSTakashi Iwai 		do_mix = false;
2259a1e908edSTakashi Iwai 
2260c30aa7b2STakashi Iwai 	if (do_mix) {
2261c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2262c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
226355196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2264c30aa7b2STakashi Iwai 	} else {
226565033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
226665033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
226755196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2268c30aa7b2STakashi Iwai 	}
2269c30aa7b2STakashi Iwai }
2270c30aa7b2STakashi Iwai 
2271c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2272c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2273c30aa7b2STakashi Iwai {
2274c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2275c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2276c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2277c30aa7b2STakashi Iwai 
2278c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2279c30aa7b2STakashi Iwai 		return 0;
2280c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2281c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2282a1e908edSTakashi Iwai 			   spec->aamix_out_paths[0],
2283a1e908edSTakashi Iwai 			   spec->autocfg.line_out_type);
2284c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2285a1e908edSTakashi Iwai 			   spec->aamix_out_paths[1],
2286a1e908edSTakashi Iwai 			   AUTO_PIN_HP_OUT);
2287c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2288a1e908edSTakashi Iwai 			   spec->aamix_out_paths[2],
2289a1e908edSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
2290c30aa7b2STakashi Iwai 	return 1;
2291c30aa7b2STakashi Iwai }
2292c30aa7b2STakashi Iwai 
2293c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2294c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2295c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2296c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2297c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2298c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2299c30aa7b2STakashi Iwai };
2300c30aa7b2STakashi Iwai 
2301c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2302c30aa7b2STakashi Iwai {
2303c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2304c30aa7b2STakashi Iwai 
2305c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2306c30aa7b2STakashi Iwai 		return 0;
2307c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2308c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2309c30aa7b2STakashi Iwai 		return 0;
2310c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2311c30aa7b2STakashi Iwai 		return -ENOMEM;
2312a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2313c30aa7b2STakashi Iwai 	return 0;
2314c30aa7b2STakashi Iwai }
2315c30aa7b2STakashi Iwai 
2316c30aa7b2STakashi Iwai /*
2317352f7f91STakashi Iwai  * shared headphone/mic handling
2318352f7f91STakashi Iwai  */
2319352f7f91STakashi Iwai 
2320352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2321352f7f91STakashi Iwai 
2322352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2323967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2324352f7f91STakashi Iwai {
2325352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2326967303daSTakashi Iwai 	bool as_mic;
2327352f7f91STakashi Iwai 	unsigned int val;
2328967303daSTakashi Iwai 	hda_nid_t pin;
2329967303daSTakashi Iwai 
2330967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2331967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2332967303daSTakashi Iwai 
2333967303daSTakashi Iwai 	if (!force) {
2334967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2335967303daSTakashi Iwai 		if (as_mic) {
2336967303daSTakashi Iwai 			if (val & PIN_IN)
2337967303daSTakashi Iwai 				return;
2338967303daSTakashi Iwai 		} else {
2339967303daSTakashi Iwai 			if (val & PIN_OUT)
2340967303daSTakashi Iwai 				return;
2341967303daSTakashi Iwai 		}
2342967303daSTakashi Iwai 	}
2343352f7f91STakashi Iwai 
2344352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2345967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2346967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2347967303daSTakashi Iwai 	 */
2348352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2349352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2350352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2351352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
23527594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2353967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2354352f7f91STakashi Iwai 	}
2355352f7f91STakashi Iwai 
23568ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2357967303daSTakashi Iwai 		if (as_mic)
2358967303daSTakashi Iwai 			val |= PIN_IN;
2359967303daSTakashi Iwai 		else
2360967303daSTakashi Iwai 			val = PIN_HP;
23612c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2362963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
23638ba955ceSTakashi Iwai 	}
2364352f7f91STakashi Iwai }
2365352f7f91STakashi Iwai 
2366352f7f91STakashi Iwai /* create a shared input with the headphone out */
2367967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2368352f7f91STakashi Iwai {
2369352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2370352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2371352f7f91STakashi Iwai 	unsigned int defcfg;
2372352f7f91STakashi Iwai 	hda_nid_t nid;
2373352f7f91STakashi Iwai 
2374967303daSTakashi Iwai 	if (!spec->hp_mic) {
2375967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2376352f7f91STakashi Iwai 			return 0;
2377967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2378967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2379967303daSTakashi Iwai 		 */
2380967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2381967303daSTakashi Iwai 			return 0;
2382967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2383352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2384352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2385352f7f91STakashi Iwai 				return 0;
2386967303daSTakashi Iwai 		}
2387967303daSTakashi Iwai 	}
2388352f7f91STakashi Iwai 
2389967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2390967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2391967303daSTakashi Iwai 		return 0;
2392967303daSTakashi Iwai 
2393967303daSTakashi Iwai 	nid = 0;
2394967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2395967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2396967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2397967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2398967303daSTakashi Iwai 	if (!nid)
2399967303daSTakashi Iwai 		return 0;
2400352f7f91STakashi Iwai 
2401352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2402352f7f91STakashi Iwai 		return 0; /* no input */
2403352f7f91STakashi Iwai 
2404967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2405967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2406cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2407967303daSTakashi Iwai 	cfg->num_inputs++;
2408967303daSTakashi Iwai 	spec->hp_mic = 1;
2409967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2410967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2411967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
2412352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2413352f7f91STakashi Iwai 	return 0;
2414352f7f91STakashi Iwai }
2415352f7f91STakashi Iwai 
2416978e77e7STakashi Iwai /*
2417978e77e7STakashi Iwai  * output jack mode
2418978e77e7STakashi Iwai  */
24195f171baaSTakashi Iwai 
24205f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
24215f171baaSTakashi Iwai 
24225f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
24235f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
24245f171baaSTakashi Iwai };
24255f171baaSTakashi Iwai 
2426978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2427978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2428978e77e7STakashi Iwai {
24295f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2430978e77e7STakashi Iwai }
2431978e77e7STakashi Iwai 
2432978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2433978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2434978e77e7STakashi Iwai {
2435978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2436978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2437978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2438978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2439978e77e7STakashi Iwai 	else
2440978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2441978e77e7STakashi Iwai 	return 0;
2442978e77e7STakashi Iwai }
2443978e77e7STakashi Iwai 
2444978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2445978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2446978e77e7STakashi Iwai {
2447978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2448978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2449978e77e7STakashi Iwai 	unsigned int val;
2450978e77e7STakashi Iwai 
2451978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2452978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2453978e77e7STakashi Iwai 		return 0;
2454978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2455978e77e7STakashi Iwai 	return 1;
2456978e77e7STakashi Iwai }
2457978e77e7STakashi Iwai 
2458978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2459978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2460978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2461978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2462978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2463978e77e7STakashi Iwai };
2464978e77e7STakashi Iwai 
2465978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2466978e77e7STakashi Iwai {
2467978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2468978e77e7STakashi Iwai 	int i;
2469978e77e7STakashi Iwai 
2470978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2471978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2472978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2473978e77e7STakashi Iwai 			return true;
2474978e77e7STakashi Iwai 	}
2475978e77e7STakashi Iwai 	return false;
2476978e77e7STakashi Iwai }
2477978e77e7STakashi Iwai 
2478978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2479978e77e7STakashi Iwai 			       char *name, size_t name_len)
2480978e77e7STakashi Iwai {
2481978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2482978e77e7STakashi Iwai 	int idx = 0;
2483978e77e7STakashi Iwai 
2484978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2485978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2486978e77e7STakashi Iwai 
2487978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2488978e77e7STakashi Iwai 		;
2489978e77e7STakashi Iwai }
2490978e77e7STakashi Iwai 
24915f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
24925f171baaSTakashi Iwai {
24935f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2494f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
24955f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
24965f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
24975f171baaSTakashi Iwai 			return 2;
24985f171baaSTakashi Iwai 	}
24995f171baaSTakashi Iwai 	return 1;
25005f171baaSTakashi Iwai }
25015f171baaSTakashi Iwai 
2502978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2503978e77e7STakashi Iwai 				 hda_nid_t *pins)
2504978e77e7STakashi Iwai {
2505978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2506978e77e7STakashi Iwai 	int i;
2507978e77e7STakashi Iwai 
2508978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2509978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2510ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
25115f171baaSTakashi Iwai 			continue;
25125f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2513978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2514975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2515978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2516978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2517978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2518978e77e7STakashi Iwai 			if (!knew)
2519978e77e7STakashi Iwai 				return -ENOMEM;
2520978e77e7STakashi Iwai 			knew->private_value = pin;
2521978e77e7STakashi Iwai 		}
2522978e77e7STakashi Iwai 	}
2523978e77e7STakashi Iwai 
2524978e77e7STakashi Iwai 	return 0;
2525978e77e7STakashi Iwai }
2526978e77e7STakashi Iwai 
252729476558STakashi Iwai /*
252829476558STakashi Iwai  * input jack mode
252929476558STakashi Iwai  */
253029476558STakashi Iwai 
253129476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
253229476558STakashi Iwai #define NUM_VREFS	6
253329476558STakashi Iwai 
253429476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
253529476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
253629476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
253729476558STakashi Iwai };
253829476558STakashi Iwai 
253929476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
254029476558STakashi Iwai {
254129476558STakashi Iwai 	unsigned int pincap;
254229476558STakashi Iwai 
254329476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
254429476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
254529476558STakashi Iwai 	/* filter out unusual vrefs */
254629476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
254729476558STakashi Iwai 	return pincap;
254829476558STakashi Iwai }
254929476558STakashi Iwai 
255029476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
255129476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
255229476558STakashi Iwai {
255329476558STakashi Iwai 	unsigned int i, n = 0;
255429476558STakashi Iwai 
255529476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
255629476558STakashi Iwai 		if (vref_caps & (1 << i)) {
255729476558STakashi Iwai 			if (n == item_idx)
255829476558STakashi Iwai 				return i;
255929476558STakashi Iwai 			n++;
256029476558STakashi Iwai 		}
256129476558STakashi Iwai 	}
256229476558STakashi Iwai 	return 0;
256329476558STakashi Iwai }
256429476558STakashi Iwai 
256529476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
256629476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
256729476558STakashi Iwai {
256829476558STakashi Iwai 	unsigned int i, n = 0;
256929476558STakashi Iwai 
257029476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
257129476558STakashi Iwai 		if (i == idx)
257229476558STakashi Iwai 			return n;
257329476558STakashi Iwai 		if (vref_caps & (1 << i))
257429476558STakashi Iwai 			n++;
257529476558STakashi Iwai 	}
257629476558STakashi Iwai 	return 0;
257729476558STakashi Iwai }
257829476558STakashi Iwai 
257929476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
258029476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
258129476558STakashi Iwai {
258229476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258329476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
258429476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
258529476558STakashi Iwai 
258629476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
258729476558STakashi Iwai 				 vref_texts);
258829476558STakashi Iwai 	/* set the right text */
258929476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
259029476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
259129476558STakashi Iwai 	return 0;
259229476558STakashi Iwai }
259329476558STakashi Iwai 
259429476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
259529476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
259629476558STakashi Iwai {
259729476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
259829476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
259929476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
260029476558STakashi Iwai 	unsigned int idx;
260129476558STakashi Iwai 
260229476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
260329476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
260429476558STakashi Iwai 	return 0;
260529476558STakashi Iwai }
260629476558STakashi Iwai 
260729476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
260829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
260929476558STakashi Iwai {
261029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
261129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
261229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
261329476558STakashi Iwai 	unsigned int val, idx;
261429476558STakashi Iwai 
261529476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
261629476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
261729476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
261829476558STakashi Iwai 		return 0;
261929476558STakashi Iwai 
262029476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
262129476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
262229476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
262329476558STakashi Iwai 	return 1;
262429476558STakashi Iwai }
262529476558STakashi Iwai 
262629476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
262729476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
262829476558STakashi Iwai 	.info = in_jack_mode_info,
262929476558STakashi Iwai 	.get = in_jack_mode_get,
263029476558STakashi Iwai 	.put = in_jack_mode_put,
263129476558STakashi Iwai };
263229476558STakashi Iwai 
26335f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26345f171baaSTakashi Iwai {
26355f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
26365f171baaSTakashi Iwai 	int nitems = 0;
2637f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
26385f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
26395f171baaSTakashi Iwai 	return nitems ? nitems : 1;
26405f171baaSTakashi Iwai }
26415f171baaSTakashi Iwai 
264229476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
264329476558STakashi Iwai {
264429476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
264529476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2646975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
26475f171baaSTakashi Iwai 	unsigned int defcfg;
26485f171baaSTakashi Iwai 
2649f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2650f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
265129476558STakashi Iwai 
265229476558STakashi Iwai 	/* no jack mode for fixed pins */
265329476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
265429476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
265529476558STakashi Iwai 		return 0;
265629476558STakashi Iwai 
265729476558STakashi Iwai 	/* no multiple vref caps? */
26585f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
265929476558STakashi Iwai 		return 0;
266029476558STakashi Iwai 
266129476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
266229476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
266329476558STakashi Iwai 	if (!knew)
266429476558STakashi Iwai 		return -ENOMEM;
266529476558STakashi Iwai 	knew->private_value = pin;
266629476558STakashi Iwai 	return 0;
266729476558STakashi Iwai }
266829476558STakashi Iwai 
26695f171baaSTakashi Iwai /*
26705f171baaSTakashi Iwai  * HP/mic shared jack mode
26715f171baaSTakashi Iwai  */
26725f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
26735f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
26745f171baaSTakashi Iwai {
26755f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26765f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
26775f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
26785f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
26795f171baaSTakashi Iwai 	const char *text = NULL;
26805f171baaSTakashi Iwai 	int idx;
26815f171baaSTakashi Iwai 
26825f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
26835f171baaSTakashi Iwai 	uinfo->count = 1;
26845f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
26855f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
26865f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
26875f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
26885f171baaSTakashi Iwai 	if (idx < out_jacks) {
26895f171baaSTakashi Iwai 		if (out_jacks > 1)
26905f171baaSTakashi Iwai 			text = out_jack_texts[idx];
26915f171baaSTakashi Iwai 		else
26925f171baaSTakashi Iwai 			text = "Headphone Out";
26935f171baaSTakashi Iwai 	} else {
26945f171baaSTakashi Iwai 		idx -= out_jacks;
26955f171baaSTakashi Iwai 		if (in_jacks > 1) {
26965f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
26975f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
26985f171baaSTakashi Iwai 		} else
26995f171baaSTakashi Iwai 			text = "Mic In";
27005f171baaSTakashi Iwai 	}
27015f171baaSTakashi Iwai 
27025f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
27035f171baaSTakashi Iwai 	return 0;
27045f171baaSTakashi Iwai }
27055f171baaSTakashi Iwai 
27065f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
27075f171baaSTakashi Iwai {
27085f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27095f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27105f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
27115f171baaSTakashi Iwai 	int idx = 0;
27125f171baaSTakashi Iwai 
27135f171baaSTakashi Iwai 	if (val & PIN_OUT) {
27145f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
27155f171baaSTakashi Iwai 			idx = 1;
27165f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
27175f171baaSTakashi Iwai 		idx = out_jacks;
27185f171baaSTakashi Iwai 		if (in_jacks > 1) {
27195f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27205f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
27215f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
27225f171baaSTakashi Iwai 		}
27235f171baaSTakashi Iwai 	}
27245f171baaSTakashi Iwai 	return idx;
27255f171baaSTakashi Iwai }
27265f171baaSTakashi Iwai 
27275f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
27285f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27295f171baaSTakashi Iwai {
27305f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27315f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27325f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
27335f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
27345f171baaSTakashi Iwai 	return 0;
27355f171baaSTakashi Iwai }
27365f171baaSTakashi Iwai 
27375f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
27385f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27395f171baaSTakashi Iwai {
27405f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27415f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27425f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27435f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27445f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
27455f171baaSTakashi Iwai 
27465f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
27475f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
27485f171baaSTakashi Iwai 	if (oldval == idx)
27495f171baaSTakashi Iwai 		return 0;
27505f171baaSTakashi Iwai 
27515f171baaSTakashi Iwai 	if (idx < out_jacks) {
27525f171baaSTakashi Iwai 		if (out_jacks > 1)
27535f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
27545f171baaSTakashi Iwai 		else
27555f171baaSTakashi Iwai 			val = PIN_HP;
27565f171baaSTakashi Iwai 	} else {
27575f171baaSTakashi Iwai 		idx -= out_jacks;
27585f171baaSTakashi Iwai 		if (in_jacks > 1) {
27595f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27605f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
27613f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
27623f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
27635f171baaSTakashi Iwai 		} else
276416c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
27655f171baaSTakashi Iwai 	}
27665f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2767963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
27688ba955ceSTakashi Iwai 
27695f171baaSTakashi Iwai 	return 1;
27705f171baaSTakashi Iwai }
27715f171baaSTakashi Iwai 
27725f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
27735f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
27745f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
27755f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
27765f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
27775f171baaSTakashi Iwai };
27785f171baaSTakashi Iwai 
27795f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
27805f171baaSTakashi Iwai {
27815f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
27825f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
27835f171baaSTakashi Iwai 
27845f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
27855f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
27865f171baaSTakashi Iwai 	if (!knew)
27875f171baaSTakashi Iwai 		return -ENOMEM;
27885f171baaSTakashi Iwai 	knew->private_value = pin;
27898ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
27905f171baaSTakashi Iwai 	return 0;
27915f171baaSTakashi Iwai }
2792352f7f91STakashi Iwai 
2793352f7f91STakashi Iwai /*
2794352f7f91STakashi Iwai  * Parse input paths
2795352f7f91STakashi Iwai  */
2796352f7f91STakashi Iwai 
2797352f7f91STakashi Iwai /* add the powersave loopback-list entry */
27980186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2799352f7f91STakashi Iwai {
2800352f7f91STakashi Iwai 	struct hda_amp_list *list;
2801352f7f91STakashi Iwai 
28020186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
28030186f4f4STakashi Iwai 	if (!list)
28040186f4f4STakashi Iwai 		return -ENOMEM;
2805352f7f91STakashi Iwai 	list->nid = mix;
2806352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2807352f7f91STakashi Iwai 	list->idx = idx;
28080186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
28090186f4f4STakashi Iwai 	return 0;
2810cb53c626STakashi Iwai }
2811cb53c626STakashi Iwai 
28122ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
28132ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
28142ded3e5bSTakashi Iwai  */
28152ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
28162ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
28172ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
28182ded3e5bSTakashi Iwai {
28192ded3e5bSTakashi Iwai 	int idx, num_conns;
28202ded3e5bSTakashi Iwai 	const hda_nid_t *list;
28212ded3e5bSTakashi Iwai 	hda_nid_t nid;
28222ded3e5bSTakashi Iwai 
28232ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
28242ded3e5bSTakashi Iwai 	if (idx < 0)
28252ded3e5bSTakashi Iwai 		return false;
28262ded3e5bSTakashi Iwai 
28272ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
28282ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
28292ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28302ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
28312ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28322ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
28332ded3e5bSTakashi Iwai 		return true;
28342ded3e5bSTakashi Iwai 
28352ded3e5bSTakashi Iwai 	/* check leaf node */
28362ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
28372ded3e5bSTakashi Iwai 	if (num_conns < idx)
28382ded3e5bSTakashi Iwai 		return false;
28392ded3e5bSTakashi Iwai 	nid = list[idx];
28402ded3e5bSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
28412ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
28422ded3e5bSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
28432ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
28442ded3e5bSTakashi Iwai 
28452ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
28462ded3e5bSTakashi Iwai }
28472ded3e5bSTakashi Iwai 
2848352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2849196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2850196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2851352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
28521da177e4SLinus Torvalds {
2853352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2854352f7f91STakashi Iwai 	struct nid_path *path;
28552ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
2856352f7f91STakashi Iwai 	int err, idx;
28571da177e4SLinus Torvalds 
28582ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
28592ded3e5bSTakashi Iwai 		return 0;
2860352f7f91STakashi Iwai 
28613ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2862352f7f91STakashi Iwai 	if (!path)
2863352f7f91STakashi Iwai 		return -EINVAL;
28640c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2865196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2866352f7f91STakashi Iwai 
2867352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
28682ded3e5bSTakashi Iwai 	if (mix_val) {
28692ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
2870d13bd412STakashi Iwai 		if (err < 0)
28711da177e4SLinus Torvalds 			return err;
28722ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
28731da177e4SLinus Torvalds 	}
28741da177e4SLinus Torvalds 
28752ded3e5bSTakashi Iwai 	if (mute_val) {
28762ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
2877d13bd412STakashi Iwai 		if (err < 0)
28781da177e4SLinus Torvalds 			return err;
28792ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
28801da177e4SLinus Torvalds 	}
28811da177e4SLinus Torvalds 
2882352f7f91STakashi Iwai 	path->active = true;
28830186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
28840186f4f4STakashi Iwai 	if (err < 0)
28850186f4f4STakashi Iwai 		return err;
2886e4a395e7STakashi Iwai 
2887e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
2888e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
2889e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
2890e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
2891e4a395e7STakashi Iwai 		if (path) {
2892e4a395e7STakashi Iwai 			print_nid_path("loopback-merge", path);
2893e4a395e7STakashi Iwai 			path->active = true;
2894e4a395e7STakashi Iwai 			spec->loopback_merge_path =
2895e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
2896e4a395e7STakashi Iwai 		}
2897e4a395e7STakashi Iwai 	}
2898e4a395e7STakashi Iwai 
2899352f7f91STakashi Iwai 	return 0;
29001da177e4SLinus Torvalds }
29011da177e4SLinus Torvalds 
2902352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
29031da177e4SLinus Torvalds {
2904352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2905352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2906352f7f91STakashi Iwai }
2907352f7f91STakashi Iwai 
2908352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2909352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2910352f7f91STakashi Iwai {
2911352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2912352f7f91STakashi Iwai 	hda_nid_t nid;
2913352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2914352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2915352f7f91STakashi Iwai 	int i, nums = 0;
2916352f7f91STakashi Iwai 
2917352f7f91STakashi Iwai 	nid = codec->start_nid;
2918352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2919352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2920352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2921352f7f91STakashi Iwai 
2922352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2923352f7f91STakashi Iwai 			continue;
2924352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2925352f7f91STakashi Iwai 		if (++nums >= max_nums)
2926352f7f91STakashi Iwai 			break;
2927352f7f91STakashi Iwai 	}
2928352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
29290ffd534eSTakashi Iwai 
29300ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
29310ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
29320ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
29330ffd534eSTakashi Iwai 
2934352f7f91STakashi Iwai 	return nums;
2935352f7f91STakashi Iwai }
2936352f7f91STakashi Iwai 
2937352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2938352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2939352f7f91STakashi Iwai  */
2940352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2941352f7f91STakashi Iwai {
2942352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2943352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
29443a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2945352f7f91STakashi Iwai 	int i, n, nums;
2946352f7f91STakashi Iwai 
2947352f7f91STakashi Iwai 	nums = 0;
29483a65bcdcSTakashi Iwai 	ok_bits = 0;
2949352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2950352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
29513a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2952352f7f91STakashi Iwai 				break;
2953352f7f91STakashi Iwai 		}
29543a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
29553a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
29563a65bcdcSTakashi Iwai 			nums++;
29573a65bcdcSTakashi Iwai 		}
2958352f7f91STakashi Iwai 	}
2959352f7f91STakashi Iwai 
29603a65bcdcSTakashi Iwai 	if (!ok_bits) {
2961352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2962352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2963352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
29643a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2965352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2966352f7f91STakashi Iwai 					break;
2967352f7f91STakashi Iwai 				}
2968352f7f91STakashi Iwai 			}
2969352f7f91STakashi Iwai 		}
2970352f7f91STakashi Iwai 
2971352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2972352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2973352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
29743a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
29753a65bcdcSTakashi Iwai 		nums = 0;
29763a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
29773a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
29783a65bcdcSTakashi Iwai 				continue;
29793a65bcdcSTakashi Iwai 			if (n != nums) {
29803a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2981980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2982980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2983980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
29843a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
29853a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
29863a65bcdcSTakashi Iwai 				}
2987980428ceSTakashi Iwai 			}
29883a65bcdcSTakashi Iwai 			nums++;
29893a65bcdcSTakashi Iwai 		}
2990352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2991352f7f91STakashi Iwai 	}
2992352f7f91STakashi Iwai 
2993967303daSTakashi Iwai 	if (imux->num_items == 1 ||
2994967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
2995352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2996352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2997352f7f91STakashi Iwai 	}
2998352f7f91STakashi Iwai 
2999352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3000352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3001352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3002352f7f91STakashi Iwai 
30031da177e4SLinus Torvalds 	return 0;
30041da177e4SLinus Torvalds }
30051da177e4SLinus Torvalds 
3006f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3007f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
30089dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
30099dba205bSTakashi Iwai 				const char *label, int anchor)
3010f3fc0b0bSTakashi Iwai {
3011f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3012f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3013f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3014f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3015f3fc0b0bSTakashi Iwai 	int c;
3016f3fc0b0bSTakashi Iwai 
3017f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3018f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3019f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3020f3fc0b0bSTakashi Iwai 
3021f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3022f3fc0b0bSTakashi Iwai 			continue;
3023f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3024f3fc0b0bSTakashi Iwai 		if (!path)
3025f3fc0b0bSTakashi Iwai 			continue;
3026f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
3027f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3028f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3029f3fc0b0bSTakashi Iwai 
3030f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3031967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3032967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3033f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
30349dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
3035f3fc0b0bSTakashi Iwai 			imux_added = true;
3036f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3037f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3038f3fc0b0bSTakashi Iwai 		}
3039f3fc0b0bSTakashi Iwai 	}
3040f3fc0b0bSTakashi Iwai 
3041f3fc0b0bSTakashi Iwai 	return 0;
3042f3fc0b0bSTakashi Iwai }
3043f3fc0b0bSTakashi Iwai 
30441da177e4SLinus Torvalds /*
3045352f7f91STakashi Iwai  * create playback/capture controls for input pins
30461da177e4SLinus Torvalds  */
30479dba205bSTakashi Iwai 
3048c970042cSTakashi Iwai /* fill the label for each input at first */
3049c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3050c970042cSTakashi Iwai {
3051c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3052c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3053c970042cSTakashi Iwai 	int i;
3054c970042cSTakashi Iwai 
3055c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3056c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3057c970042cSTakashi Iwai 		const char *label;
3058c970042cSTakashi Iwai 		int j, idx;
3059c970042cSTakashi Iwai 
3060c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3061c970042cSTakashi Iwai 			continue;
3062c970042cSTakashi Iwai 
3063c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3064c970042cSTakashi Iwai 		idx = 0;
30658e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3066c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3067c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3068c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3069c970042cSTakashi Iwai 				break;
3070c970042cSTakashi Iwai 			}
3071c970042cSTakashi Iwai 		}
3072c970042cSTakashi Iwai 
3073c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3074c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3075c970042cSTakashi Iwai 	}
3076c970042cSTakashi Iwai 
3077c970042cSTakashi Iwai 	return 0;
3078c970042cSTakashi Iwai }
3079c970042cSTakashi Iwai 
30809dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
30819dba205bSTakashi Iwai 
3082352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3083a7da6ce5STakashi Iwai {
3084352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3085352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3086352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3087352f7f91STakashi Iwai 	int num_adcs;
3088c970042cSTakashi Iwai 	int i, err;
30892c12c30dSTakashi Iwai 	unsigned int val;
3090a7da6ce5STakashi Iwai 
3091352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3092352f7f91STakashi Iwai 	if (num_adcs < 0)
3093352f7f91STakashi Iwai 		return 0;
3094352f7f91STakashi Iwai 
3095c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3096c970042cSTakashi Iwai 	if (err < 0)
3097c970042cSTakashi Iwai 		return err;
3098c970042cSTakashi Iwai 
3099352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3100352f7f91STakashi Iwai 		hda_nid_t pin;
3101352f7f91STakashi Iwai 
3102352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3103352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3104352f7f91STakashi Iwai 			continue;
3105352f7f91STakashi Iwai 
31062c12c30dSTakashi Iwai 		val = PIN_IN;
31072c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
31082c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
310993c9d8aeSTakashi Iwai 		if (pin != spec->hp_mic_pin)
31102c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
31112c12c30dSTakashi Iwai 
3112352f7f91STakashi Iwai 		if (mixer) {
3113352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3114196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3115c970042cSTakashi Iwai 						       spec->input_labels[i],
3116c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3117c970042cSTakashi Iwai 						       mixer);
3118a7da6ce5STakashi Iwai 				if (err < 0)
3119a7da6ce5STakashi Iwai 					return err;
3120a7da6ce5STakashi Iwai 			}
3121352f7f91STakashi Iwai 		}
3122352f7f91STakashi Iwai 
3123c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3124c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3125f3fc0b0bSTakashi Iwai 		if (err < 0)
3126f3fc0b0bSTakashi Iwai 			return err;
312729476558STakashi Iwai 
3128f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
312929476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
313029476558STakashi Iwai 			if (err < 0)
313129476558STakashi Iwai 				return err;
313229476558STakashi Iwai 		}
3133352f7f91STakashi Iwai 	}
3134f3fc0b0bSTakashi Iwai 
3135f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
3136f1e762ddSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input &&
3137f1e762ddSTakashi Iwai 	    snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
31389dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3139f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3140f3fc0b0bSTakashi Iwai 		if (err < 0)
3141f3fc0b0bSTakashi Iwai 			return err;
3142352f7f91STakashi Iwai 	}
3143352f7f91STakashi Iwai 
3144a7da6ce5STakashi Iwai 	return 0;
3145a7da6ce5STakashi Iwai }
3146a7da6ce5STakashi Iwai 
31471da177e4SLinus Torvalds 
3148352f7f91STakashi Iwai /*
3149352f7f91STakashi Iwai  * input source mux
3150352f7f91STakashi Iwai  */
3151352f7f91STakashi Iwai 
3152c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3153c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3154352f7f91STakashi Iwai {
3155352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3156b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3157b56fa1edSDavid Henningsson 		snd_BUG();
3158b56fa1edSDavid Henningsson 		return NULL;
3159b56fa1edSDavid Henningsson 	}
3160352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3161352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3162d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3163b56fa1edSDavid Henningsson 		snd_BUG();
3164b56fa1edSDavid Henningsson 		return NULL;
3165b56fa1edSDavid Henningsson 	}
3166c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
316797ec558aSTakashi Iwai }
3168352f7f91STakashi Iwai 
3169352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3170352f7f91STakashi Iwai 		      unsigned int idx);
3171352f7f91STakashi Iwai 
3172352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3173352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3174352f7f91STakashi Iwai {
3175352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3176352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3177352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3178352f7f91STakashi Iwai }
3179352f7f91STakashi Iwai 
3180352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3181352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3182352f7f91STakashi Iwai {
3183352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3184352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
31852a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
31862a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3187352f7f91STakashi Iwai 
3188352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
31891da177e4SLinus Torvalds 	return 0;
31901da177e4SLinus Torvalds }
31911da177e4SLinus Torvalds 
3192352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3193352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
31941da177e4SLinus Torvalds {
3195352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
31962a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3197352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3198352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3199352f7f91STakashi Iwai }
3200352f7f91STakashi Iwai 
3201352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
32021da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3203352f7f91STakashi Iwai 	.name = "Input Source",
3204352f7f91STakashi Iwai 	.info = mux_enum_info,
3205352f7f91STakashi Iwai 	.get = mux_enum_get,
3206352f7f91STakashi Iwai 	.put = mux_enum_put,
32071da177e4SLinus Torvalds };
3208071c73adSTakashi Iwai 
320947d46abbSTakashi Iwai /*
321047d46abbSTakashi Iwai  * capture volume and capture switch ctls
321147d46abbSTakashi Iwai  */
321247d46abbSTakashi Iwai 
3213352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3214352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3215071c73adSTakashi Iwai 
321647d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3217352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3218352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3219352f7f91STakashi Iwai 			  put_call_t func, int type)
3220352f7f91STakashi Iwai {
3221352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3222352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3223352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3224352f7f91STakashi Iwai 	struct nid_path *path;
3225352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3226071c73adSTakashi Iwai 
3227352f7f91STakashi Iwai 	imux = &spec->input_mux;
3228a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3229352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
323047d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
323147d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
323247d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
323347d46abbSTakashi Iwai 	 */
3234352f7f91STakashi Iwai 	codec->cached_write = 1;
3235352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3236c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3237c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3238352f7f91STakashi Iwai 			continue;
3239352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3240352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3241352f7f91STakashi Iwai 		if (err < 0)
3242352f7f91STakashi Iwai 			goto error;
3243352f7f91STakashi Iwai 	}
3244352f7f91STakashi Iwai  error:
3245352f7f91STakashi Iwai 	codec->cached_write = 0;
3246352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3247dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec); /* flush the updates */
3248352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
3249a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3250352f7f91STakashi Iwai 	return err;
3251352f7f91STakashi Iwai }
3252352f7f91STakashi Iwai 
3253352f7f91STakashi Iwai /* capture volume ctl callbacks */
3254352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3255352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3256352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3257352f7f91STakashi Iwai 
3258352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3259352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3260352f7f91STakashi Iwai {
3261352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3262352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3263352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3264352f7f91STakashi Iwai }
3265352f7f91STakashi Iwai 
3266352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3267352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3268352f7f91STakashi Iwai 	.name = "Capture Volume",
3269352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3270352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3271352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3272352f7f91STakashi Iwai 	.info = cap_vol_info,
3273352f7f91STakashi Iwai 	.get = cap_vol_get,
3274352f7f91STakashi Iwai 	.put = cap_vol_put,
3275352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3276352f7f91STakashi Iwai };
3277352f7f91STakashi Iwai 
3278352f7f91STakashi Iwai /* capture switch ctl callbacks */
3279352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3280352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3281352f7f91STakashi Iwai 
3282352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3283352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3284352f7f91STakashi Iwai {
3285a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3286352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3287352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3288352f7f91STakashi Iwai }
3289352f7f91STakashi Iwai 
3290352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3291352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3292352f7f91STakashi Iwai 	.name = "Capture Switch",
3293352f7f91STakashi Iwai 	.info = cap_sw_info,
3294352f7f91STakashi Iwai 	.get = cap_sw_get,
3295352f7f91STakashi Iwai 	.put = cap_sw_put,
3296352f7f91STakashi Iwai };
3297352f7f91STakashi Iwai 
3298352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3299352f7f91STakashi Iwai {
3300352f7f91STakashi Iwai 	hda_nid_t nid;
3301352f7f91STakashi Iwai 	int i, depth;
3302352f7f91STakashi Iwai 
3303352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3304352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3305352f7f91STakashi Iwai 		if (depth >= path->depth)
3306352f7f91STakashi Iwai 			return -EINVAL;
3307352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3308352f7f91STakashi Iwai 		nid = path->path[i];
3309352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3310352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3311352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3312352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3313352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3314352f7f91STakashi Iwai 				int idx = path->idx[i];
3315352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3316352f7f91STakashi Iwai 					idx = 0;
3317352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3318352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3319352f7f91STakashi Iwai 			}
3320352f7f91STakashi Iwai 		}
3321352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3322352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3323352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3324352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3325352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3326352f7f91STakashi Iwai 				int idx = path->idx[i];
3327352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3328352f7f91STakashi Iwai 					idx = 0;
3329352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3330352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3331352f7f91STakashi Iwai 			}
3332352f7f91STakashi Iwai 		}
3333352f7f91STakashi Iwai 	}
3334352f7f91STakashi Iwai 	return 0;
3335352f7f91STakashi Iwai }
3336352f7f91STakashi Iwai 
3337352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3338352f7f91STakashi Iwai {
3339352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3340352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3341352f7f91STakashi Iwai 	unsigned int val;
3342352f7f91STakashi Iwai 	int i;
3343352f7f91STakashi Iwai 
3344352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3345352f7f91STakashi Iwai 		return false;
3346352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3347352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3348352f7f91STakashi Iwai 			continue;
3349352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3350352f7f91STakashi Iwai 			return false;
3351352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3352352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3353352f7f91STakashi Iwai 	}
3354352f7f91STakashi Iwai 	return false;
3355352f7f91STakashi Iwai }
3356352f7f91STakashi Iwai 
3357a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3358a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3359a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3360a35bd1e3STakashi Iwai {
3361a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3362a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3363a35bd1e3STakashi Iwai 	int ret;
3364a35bd1e3STakashi Iwai 
3365a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3366a35bd1e3STakashi Iwai 	if (ret < 0)
3367a35bd1e3STakashi Iwai 		return ret;
3368a35bd1e3STakashi Iwai 
3369a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
3370a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3371a35bd1e3STakashi Iwai 
3372a35bd1e3STakashi Iwai 	return ret;
3373a35bd1e3STakashi Iwai }
3374a35bd1e3STakashi Iwai 
3375352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3376352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3377352f7f91STakashi Iwai 			      bool inv_dmic)
3378352f7f91STakashi Iwai {
3379352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3380975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3381352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3382352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3383352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3384a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3385352f7f91STakashi Iwai 
3386352f7f91STakashi Iwai 	if (!ctl)
3387352f7f91STakashi Iwai 		return 0;
3388352f7f91STakashi Iwai 
3389352f7f91STakashi Iwai 	if (label)
3390352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3391352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3392352f7f91STakashi Iwai 	else
3393352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3394352f7f91STakashi Iwai 			 "Capture %s", sfx);
3395a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3396352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3397a35bd1e3STakashi Iwai 	if (!knew)
3398a35bd1e3STakashi Iwai 		return -ENOMEM;
3399a90229e0STakashi Iwai 	if (is_switch)
3400a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3401a35bd1e3STakashi Iwai 	if (!inv_dmic)
3402a35bd1e3STakashi Iwai 		return 0;
3403352f7f91STakashi Iwai 
3404352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3405352f7f91STakashi Iwai 	if (label)
3406352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3407352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3408352f7f91STakashi Iwai 	else
3409352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3410352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3411a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3412352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3413a35bd1e3STakashi Iwai 	if (!knew)
3414a35bd1e3STakashi Iwai 		return -ENOMEM;
3415a90229e0STakashi Iwai 	if (is_switch)
3416a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3417a35bd1e3STakashi Iwai 	return 0;
3418352f7f91STakashi Iwai }
3419352f7f91STakashi Iwai 
3420352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3421352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3422352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3423352f7f91STakashi Iwai 				     bool inv_dmic)
3424352f7f91STakashi Iwai {
3425352f7f91STakashi Iwai 	int err;
3426352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3427352f7f91STakashi Iwai 	if (err < 0)
3428352f7f91STakashi Iwai 		return err;
3429352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3430071c73adSTakashi Iwai 	if (err < 0)
3431071c73adSTakashi Iwai 		return err;
3432071c73adSTakashi Iwai 	return 0;
34331da177e4SLinus Torvalds }
3434071c73adSTakashi Iwai 
3435352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3436352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3437352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3438352f7f91STakashi Iwai {
3439352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3440352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3441352f7f91STakashi Iwai 
3442352f7f91STakashi Iwai 	if (vol_ctl) {
344312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3444352f7f91STakashi Iwai 		if (!knew)
3445352f7f91STakashi Iwai 			return -ENOMEM;
3446352f7f91STakashi Iwai 		knew->index = idx;
3447352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3448352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3449352f7f91STakashi Iwai 	}
3450352f7f91STakashi Iwai 	if (sw_ctl) {
345112c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3452352f7f91STakashi Iwai 		if (!knew)
3453352f7f91STakashi Iwai 			return -ENOMEM;
3454352f7f91STakashi Iwai 		knew->index = idx;
3455352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3456352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3457352f7f91STakashi Iwai 	}
3458352f7f91STakashi Iwai 	return 0;
3459352f7f91STakashi Iwai }
3460352f7f91STakashi Iwai 
3461352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3462352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3463352f7f91STakashi Iwai {
3464352f7f91STakashi Iwai 	struct nid_path *path;
3465352f7f91STakashi Iwai 	unsigned int ctl;
3466352f7f91STakashi Iwai 	int i;
3467352f7f91STakashi Iwai 
3468c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3469352f7f91STakashi Iwai 	if (!path)
3470352f7f91STakashi Iwai 		return 0;
3471352f7f91STakashi Iwai 	ctl = path->ctls[type];
3472352f7f91STakashi Iwai 	if (!ctl)
3473352f7f91STakashi Iwai 		return 0;
3474352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3475c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3476352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3477352f7f91STakashi Iwai 			return 0;
3478352f7f91STakashi Iwai 	}
3479352f7f91STakashi Iwai 	return ctl;
3480352f7f91STakashi Iwai }
3481352f7f91STakashi Iwai 
3482352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3483352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3484352f7f91STakashi Iwai {
3485352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3486352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3487c970042cSTakashi Iwai 	int i, err, type;
3488352f7f91STakashi Iwai 
3489352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3490352f7f91STakashi Iwai 		bool inv_dmic;
3491c970042cSTakashi Iwai 		int idx;
34929dba205bSTakashi Iwai 
3493c970042cSTakashi Iwai 		idx = imux->items[i].index;
3494c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
34959dba205bSTakashi Iwai 			continue;
3496352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3497352f7f91STakashi Iwai 
3498352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3499c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3500c970042cSTakashi Iwai 						 spec->input_labels[idx],
3501c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3502c970042cSTakashi Iwai 						 type,
3503352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3504352f7f91STakashi Iwai 						 inv_dmic);
3505d13bd412STakashi Iwai 			if (err < 0)
3506071c73adSTakashi Iwai 				return err;
3507352f7f91STakashi Iwai 		}
3508352f7f91STakashi Iwai 	}
3509071c73adSTakashi Iwai 	return 0;
3510352f7f91STakashi Iwai }
3511071c73adSTakashi Iwai 
3512352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3513352f7f91STakashi Iwai {
3514352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3515352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3516352f7f91STakashi Iwai 	int i, n, nums, err;
3517352f7f91STakashi Iwai 
3518352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3519352f7f91STakashi Iwai 		nums = 1;
3520352f7f91STakashi Iwai 	else
3521352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3522352f7f91STakashi Iwai 
3523352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3524352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3525624d914dSTakashi Iwai 		const char *name;
3526624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3527624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3528352f7f91STakashi Iwai 		if (!knew)
3529352f7f91STakashi Iwai 			return -ENOMEM;
3530352f7f91STakashi Iwai 		knew->count = nums;
3531352f7f91STakashi Iwai 	}
3532352f7f91STakashi Iwai 
3533352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3534352f7f91STakashi Iwai 		bool multi = false;
353599a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3536352f7f91STakashi Iwai 		bool inv_dmic = false;
3537352f7f91STakashi Iwai 		int vol, sw;
3538352f7f91STakashi Iwai 
3539352f7f91STakashi Iwai 		vol = sw = 0;
3540352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3541352f7f91STakashi Iwai 			struct nid_path *path;
3542c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3543352f7f91STakashi Iwai 			if (!path)
3544352f7f91STakashi Iwai 				continue;
3545352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3546352f7f91STakashi Iwai 			if (!vol)
3547352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
354899a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3549352f7f91STakashi Iwai 				multi = true;
355099a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
355199a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
355299a5592dSDavid Henningsson 					multi_cap_vol = true;
355399a5592dSDavid Henningsson 			}
3554352f7f91STakashi Iwai 			if (!sw)
3555352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
355699a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3557352f7f91STakashi Iwai 				multi = true;
355899a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
355999a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
356099a5592dSDavid Henningsson 					multi_cap_vol = true;
356199a5592dSDavid Henningsson 			}
3562352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3563352f7f91STakashi Iwai 				inv_dmic = true;
3564352f7f91STakashi Iwai 		}
3565352f7f91STakashi Iwai 
3566352f7f91STakashi Iwai 		if (!multi)
3567352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3568352f7f91STakashi Iwai 							inv_dmic);
3569ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3570352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3571352f7f91STakashi Iwai 		else
3572352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3573d13bd412STakashi Iwai 		if (err < 0)
3574071c73adSTakashi Iwai 			return err;
3575071c73adSTakashi Iwai 	}
3576071c73adSTakashi Iwai 
35771da177e4SLinus Torvalds 	return 0;
35781da177e4SLinus Torvalds }
35791da177e4SLinus Torvalds 
3580352f7f91STakashi Iwai /*
3581352f7f91STakashi Iwai  * add mic boosts if needed
3582352f7f91STakashi Iwai  */
35836f7c83afSTakashi Iwai 
35846f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
35856f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
35866f7c83afSTakashi Iwai 			    int dir, int idx)
35876f7c83afSTakashi Iwai {
35886f7c83afSTakashi Iwai 	unsigned int step;
35896f7c83afSTakashi Iwai 
35906f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
35916f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
35926f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
35936f7c83afSTakashi Iwai 		return false;
35946f7c83afSTakashi Iwai 
35956f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
35966f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
35976f7c83afSTakashi Iwai 	if (step < 0x20)
35986f7c83afSTakashi Iwai 		return false;
35996f7c83afSTakashi Iwai 	return true;
36006f7c83afSTakashi Iwai }
36016f7c83afSTakashi Iwai 
36026f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
36036f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
36046f7c83afSTakashi Iwai 				       struct nid_path *path)
36056f7c83afSTakashi Iwai {
36066f7c83afSTakashi Iwai 	unsigned int val = 0;
36076f7c83afSTakashi Iwai 	hda_nid_t nid;
36086f7c83afSTakashi Iwai 	int depth;
36096f7c83afSTakashi Iwai 
36106f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
36116f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
36126f7c83afSTakashi Iwai 			break;
36136f7c83afSTakashi Iwai 		nid = path->path[depth];
36146f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
36156f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
36166f7c83afSTakashi Iwai 			break;
36176f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
36186f7c83afSTakashi Iwai 					   path->idx[depth])) {
36196f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
36206f7c83afSTakashi Iwai 						  HDA_INPUT);
36216f7c83afSTakashi Iwai 			break;
36226f7c83afSTakashi Iwai 		}
36236f7c83afSTakashi Iwai 	}
36246f7c83afSTakashi Iwai 
36256f7c83afSTakashi Iwai 	return val;
36266f7c83afSTakashi Iwai }
36276f7c83afSTakashi Iwai 
3628352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3629352f7f91STakashi Iwai {
3630352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3631352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
36326f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3633a35bd1e3STakashi Iwai 	int i;
3634352f7f91STakashi Iwai 
36356f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
36366f7c83afSTakashi Iwai 		return 0;
36376f7c83afSTakashi Iwai 
36386f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3639352f7f91STakashi Iwai 		struct nid_path *path;
3640352f7f91STakashi Iwai 		unsigned int val;
36416f7c83afSTakashi Iwai 		int idx;
3642975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3643352f7f91STakashi Iwai 
36446f7c83afSTakashi Iwai 		idx = imux->items[i].index;
36456f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
364602aba550SDavid Henningsson 			continue;
364702aba550SDavid Henningsson 
36486f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
36491799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
36506f7c83afSTakashi Iwai 			continue;
36516f7c83afSTakashi Iwai 
36526f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
36536f7c83afSTakashi Iwai 		if (!path)
36546f7c83afSTakashi Iwai 			continue;
36556f7c83afSTakashi Iwai 
36566f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
36576f7c83afSTakashi Iwai 		if (!val)
36586f7c83afSTakashi Iwai 			continue;
36596f7c83afSTakashi Iwai 
36606f7c83afSTakashi Iwai 		/* create a boost control */
3661352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
36626f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3663a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3664a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3665a35bd1e3STakashi Iwai 			return -ENOMEM;
3666352f7f91STakashi Iwai 
3667352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3668352f7f91STakashi Iwai 	}
3669352f7f91STakashi Iwai 	return 0;
3670352f7f91STakashi Iwai }
3671352f7f91STakashi Iwai 
3672352f7f91STakashi Iwai /*
3673352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3674352f7f91STakashi Iwai  */
3675352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3676352f7f91STakashi Iwai {
3677352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
36780c8c0f56STakashi Iwai 	struct nid_path *path;
3679352f7f91STakashi Iwai 	int i, nums;
36802c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3681352f7f91STakashi Iwai 
3682352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3683352f7f91STakashi Iwai 	nums = 0;
3684352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
36852c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3686352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3687352f7f91STakashi Iwai 		if (!dig_nid)
3688352f7f91STakashi Iwai 			continue;
36893ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
36900c8c0f56STakashi Iwai 		if (!path)
3691352f7f91STakashi Iwai 			continue;
36920c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3693e1284af7STakashi Iwai 		path->active = true;
3694196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
36952c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3696352f7f91STakashi Iwai 		if (!nums) {
3697352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3698352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3699352f7f91STakashi Iwai 		} else {
3700352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3701352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3702352f7f91STakashi Iwai 			break;
3703352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3704352f7f91STakashi Iwai 		}
3705352f7f91STakashi Iwai 		nums++;
3706352f7f91STakashi Iwai 	}
3707352f7f91STakashi Iwai 
3708352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
37092c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3710352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3711352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3712352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3713352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3714352f7f91STakashi Iwai 				continue;
3715352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3716352f7f91STakashi Iwai 				continue;
37172c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3718352f7f91STakashi Iwai 			if (path) {
37190c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3720352f7f91STakashi Iwai 				path->active = true;
3721352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
37222430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
37232c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3724352f7f91STakashi Iwai 				break;
3725352f7f91STakashi Iwai 			}
3726352f7f91STakashi Iwai 		}
3727352f7f91STakashi Iwai 	}
3728352f7f91STakashi Iwai }
3729352f7f91STakashi Iwai 
37301da177e4SLinus Torvalds 
37311da177e4SLinus Torvalds /*
3732352f7f91STakashi Iwai  * input MUX handling
37331da177e4SLinus Torvalds  */
37341da177e4SLinus Torvalds 
3735352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3736352f7f91STakashi Iwai 
3737352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3738352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3739352f7f91STakashi Iwai 		      unsigned int idx)
3740352f7f91STakashi Iwai {
3741352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3742352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
374355196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3744352f7f91STakashi Iwai 
3745352f7f91STakashi Iwai 	imux = &spec->input_mux;
3746352f7f91STakashi Iwai 	if (!imux->num_items)
37471da177e4SLinus Torvalds 		return 0;
37481da177e4SLinus Torvalds 
3749352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3750352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3751352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3752352f7f91STakashi Iwai 		return 0;
3753352f7f91STakashi Iwai 
375455196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
375555196fffSTakashi Iwai 	if (!old_path)
3756352f7f91STakashi Iwai 		return 0;
375755196fffSTakashi Iwai 	if (old_path->active)
375855196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3759352f7f91STakashi Iwai 
3760352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3761352f7f91STakashi Iwai 
3762967303daSTakashi Iwai 	if (spec->hp_mic)
3763967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3764352f7f91STakashi Iwai 
3765352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3766352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3767352f7f91STakashi Iwai 
3768c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3769352f7f91STakashi Iwai 	if (!path)
3770352f7f91STakashi Iwai 		return 0;
3771352f7f91STakashi Iwai 	if (path->active)
3772352f7f91STakashi Iwai 		return 0;
3773352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3774352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3775a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
377655196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
37771da177e4SLinus Torvalds 	return 1;
37781da177e4SLinus Torvalds }
37791da177e4SLinus Torvalds 
37801da177e4SLinus Torvalds 
37811da177e4SLinus Torvalds /*
3782352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
37831da177e4SLinus Torvalds  */
3784352f7f91STakashi Iwai 
3785352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3786352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
37871da177e4SLinus Torvalds {
378860ea8ca2STakashi Iwai 	int i;
378960ea8ca2STakashi Iwai 	bool present = false;
37901da177e4SLinus Torvalds 
3791352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3792352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3793352f7f91STakashi Iwai 		if (!nid)
3794352f7f91STakashi Iwai 			break;
37950b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
37960b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
37970b4df931STakashi Iwai 			continue;
379860ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
379960ea8ca2STakashi Iwai 			present = true;
38001da177e4SLinus Torvalds 	}
3801352f7f91STakashi Iwai 	return present;
38021da177e4SLinus Torvalds }
38031da177e4SLinus Torvalds 
3804352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3805352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3806e80c60f3STakashi Iwai 			int *paths, bool mute)
38071da177e4SLinus Torvalds {
3808352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3809352f7f91STakashi Iwai 	int i;
38101da177e4SLinus Torvalds 
3811352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3812352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3813967303daSTakashi Iwai 		unsigned int val, oldval;
3814352f7f91STakashi Iwai 		if (!nid)
3815352f7f91STakashi Iwai 			break;
38167eebffd3STakashi Iwai 
38177eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
3818e80c60f3STakashi Iwai 			struct nid_path *path;
3819e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
3820e80c60f3STakashi Iwai 
3821e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
3822e80c60f3STakashi Iwai 			if (!path)
3823e80c60f3STakashi Iwai 				continue;
3824e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
3825e80c60f3STakashi Iwai 			if (!mute_nid)
3826e80c60f3STakashi Iwai 				continue;
38277eebffd3STakashi Iwai 			if (mute)
3828e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
38297eebffd3STakashi Iwai 			else
3830e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
38317eebffd3STakashi Iwai 			set_pin_eapd(codec, nid, !mute);
38327eebffd3STakashi Iwai 			continue;
38337eebffd3STakashi Iwai 		}
38347eebffd3STakashi Iwai 
3835967303daSTakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
3836967303daSTakashi Iwai 		if (oldval & PIN_IN)
3837967303daSTakashi Iwai 			continue; /* no mute for inputs */
3838352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3839352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3840352f7f91STakashi Iwai 		 */
38412c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
3842967303daSTakashi Iwai 			val = oldval & ~PIN_HP;
38432c12c30dSTakashi Iwai 		else
3844352f7f91STakashi Iwai 			val = 0;
38452c12c30dSTakashi Iwai 		if (!mute)
3846967303daSTakashi Iwai 			val |= oldval;
38472c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
38482c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
38492c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
38502c12c30dSTakashi Iwai 		 * init / resume again
38512c12c30dSTakashi Iwai 		 */
38522c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3853d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3854352f7f91STakashi Iwai 	}
3855352f7f91STakashi Iwai }
38561da177e4SLinus Torvalds 
3857352f7f91STakashi Iwai /* Toggle outputs muting */
38585d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3859352f7f91STakashi Iwai {
3860352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3861e80c60f3STakashi Iwai 	int *paths;
3862352f7f91STakashi Iwai 	int on;
3863352f7f91STakashi Iwai 
3864352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3865352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3866352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3867352f7f91STakashi Iwai 	 */
3868e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3869e80c60f3STakashi Iwai 		paths = spec->out_paths;
3870e80c60f3STakashi Iwai 	else
3871e80c60f3STakashi Iwai 		paths = spec->hp_paths;
3872352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3873e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
3874352f7f91STakashi Iwai 
3875352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3876352f7f91STakashi Iwai 		on = 0;
3877352f7f91STakashi Iwai 	else
3878352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3879352f7f91STakashi Iwai 	on |= spec->master_mute;
388047b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3881e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3882e80c60f3STakashi Iwai 		paths = spec->out_paths;
3883e80c60f3STakashi Iwai 	else
3884e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
3885352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
3886e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
3887352f7f91STakashi Iwai 
3888352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3889352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3890352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3891352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3892352f7f91STakashi Iwai 		return;
3893352f7f91STakashi Iwai 	if (!spec->automute_lo)
3894352f7f91STakashi Iwai 		on = 0;
3895352f7f91STakashi Iwai 	else
3896352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3897352f7f91STakashi Iwai 	on |= spec->master_mute;
389847b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3899e80c60f3STakashi Iwai 	paths = spec->out_paths;
3900352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3901e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
3902352f7f91STakashi Iwai }
39035d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3904352f7f91STakashi Iwai 
3905352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3906352f7f91STakashi Iwai {
3907352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3908352f7f91STakashi Iwai 	if (spec->automute_hook)
3909352f7f91STakashi Iwai 		spec->automute_hook(codec);
3910352f7f91STakashi Iwai 	else
39115d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
39127eebffd3STakashi Iwai 
39137eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
39147eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
39157eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
3916352f7f91STakashi Iwai }
3917352f7f91STakashi Iwai 
3918352f7f91STakashi Iwai /* standard HP-automute helper */
39195d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3920352f7f91STakashi Iwai {
3921352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
392292603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
392392603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
3924352f7f91STakashi Iwai 
392592603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
392692603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
392792603c59STakashi Iwai 		pins++;
392892603c59STakashi Iwai 		num_pins--;
392992603c59STakashi Iwai 	}
393092603c59STakashi Iwai 
393192603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
3932352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3933352f7f91STakashi Iwai 		return;
3934352f7f91STakashi Iwai 	call_update_outputs(codec);
3935352f7f91STakashi Iwai }
39365d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3937352f7f91STakashi Iwai 
3938352f7f91STakashi Iwai /* standard line-out-automute helper */
39395d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3940352f7f91STakashi Iwai {
3941352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3942352f7f91STakashi Iwai 
3943352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3944352f7f91STakashi Iwai 		return;
3945352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3946352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3947352f7f91STakashi Iwai 		return;
3948352f7f91STakashi Iwai 
3949352f7f91STakashi Iwai 	spec->line_jack_present =
3950352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3951352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3952352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3953352f7f91STakashi Iwai 		return;
3954352f7f91STakashi Iwai 	call_update_outputs(codec);
3955352f7f91STakashi Iwai }
39565d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3957352f7f91STakashi Iwai 
3958352f7f91STakashi Iwai /* standard mic auto-switch helper */
39595d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3960352f7f91STakashi Iwai {
3961352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3962352f7f91STakashi Iwai 	int i;
3963352f7f91STakashi Iwai 
3964352f7f91STakashi Iwai 	if (!spec->auto_mic)
3965352f7f91STakashi Iwai 		return;
3966352f7f91STakashi Iwai 
3967352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
39680b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
39690b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
39700b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
39710b4df931STakashi Iwai 			continue;
397260ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
3973352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3974352f7f91STakashi Iwai 			return;
3975352f7f91STakashi Iwai 		}
3976352f7f91STakashi Iwai 	}
3977352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
39781da177e4SLinus Torvalds }
39795d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
39801da177e4SLinus Torvalds 
398177afe0e9STakashi Iwai /* call appropriate hooks */
398277afe0e9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
398377afe0e9STakashi Iwai {
398477afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
398577afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
398677afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
398777afe0e9STakashi Iwai 	else
398877afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
398977afe0e9STakashi Iwai }
399077afe0e9STakashi Iwai 
399177afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
399277afe0e9STakashi Iwai 			       struct hda_jack_tbl *jack)
399377afe0e9STakashi Iwai {
399477afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
399577afe0e9STakashi Iwai 	if (spec->line_automute_hook)
399677afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
399777afe0e9STakashi Iwai 	else
399877afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
399977afe0e9STakashi Iwai }
400077afe0e9STakashi Iwai 
400177afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
400277afe0e9STakashi Iwai 				struct hda_jack_tbl *jack)
400377afe0e9STakashi Iwai {
400477afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
400577afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
400677afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
400777afe0e9STakashi Iwai 	else
400877afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
400977afe0e9STakashi Iwai }
401077afe0e9STakashi Iwai 
4011963afde9STakashi Iwai /* update jack retasking */
4012963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4013963afde9STakashi Iwai {
4014963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4015963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4016963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4017963afde9STakashi Iwai }
4018963afde9STakashi Iwai 
40191da177e4SLinus Torvalds /*
4020352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
40211da177e4SLinus Torvalds  */
4022352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4023352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4024352f7f91STakashi Iwai {
4025352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4026352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4027352f7f91STakashi Iwai 	static const char * const texts3[] = {
4028352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
40291da177e4SLinus Torvalds 	};
40301da177e4SLinus Torvalds 
4031352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4032352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4033352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4034352f7f91STakashi Iwai }
4035352f7f91STakashi Iwai 
4036352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4037352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4038352f7f91STakashi Iwai {
4039352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4040352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4041352f7f91STakashi Iwai 	unsigned int val = 0;
4042352f7f91STakashi Iwai 	if (spec->automute_speaker)
4043352f7f91STakashi Iwai 		val++;
4044352f7f91STakashi Iwai 	if (spec->automute_lo)
4045352f7f91STakashi Iwai 		val++;
4046352f7f91STakashi Iwai 
4047352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4048352f7f91STakashi Iwai 	return 0;
4049352f7f91STakashi Iwai }
4050352f7f91STakashi Iwai 
4051352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4052352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4053352f7f91STakashi Iwai {
4054352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4055352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4056352f7f91STakashi Iwai 
4057352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4058352f7f91STakashi Iwai 	case 0:
4059352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4060352f7f91STakashi Iwai 			return 0;
4061352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4062352f7f91STakashi Iwai 		spec->automute_lo = 0;
4063352f7f91STakashi Iwai 		break;
4064352f7f91STakashi Iwai 	case 1:
4065352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4066352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4067352f7f91STakashi Iwai 				return 0;
4068352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4069352f7f91STakashi Iwai 			spec->automute_lo = 0;
4070352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4071352f7f91STakashi Iwai 			if (spec->automute_lo)
4072352f7f91STakashi Iwai 				return 0;
4073352f7f91STakashi Iwai 			spec->automute_lo = 1;
4074352f7f91STakashi Iwai 		} else
4075352f7f91STakashi Iwai 			return -EINVAL;
4076352f7f91STakashi Iwai 		break;
4077352f7f91STakashi Iwai 	case 2:
4078352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4079352f7f91STakashi Iwai 			return -EINVAL;
4080352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4081352f7f91STakashi Iwai 			return 0;
4082352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4083352f7f91STakashi Iwai 		spec->automute_lo = 1;
4084352f7f91STakashi Iwai 		break;
4085352f7f91STakashi Iwai 	default:
4086352f7f91STakashi Iwai 		return -EINVAL;
4087352f7f91STakashi Iwai 	}
4088352f7f91STakashi Iwai 	call_update_outputs(codec);
4089352f7f91STakashi Iwai 	return 1;
4090352f7f91STakashi Iwai }
4091352f7f91STakashi Iwai 
4092352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4093352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4094352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4095352f7f91STakashi Iwai 	.info = automute_mode_info,
4096352f7f91STakashi Iwai 	.get = automute_mode_get,
4097352f7f91STakashi Iwai 	.put = automute_mode_put,
4098352f7f91STakashi Iwai };
4099352f7f91STakashi Iwai 
4100352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4101352f7f91STakashi Iwai {
4102352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4103352f7f91STakashi Iwai 
410412c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4105352f7f91STakashi Iwai 		return -ENOMEM;
4106352f7f91STakashi Iwai 	return 0;
4107352f7f91STakashi Iwai }
4108352f7f91STakashi Iwai 
4109352f7f91STakashi Iwai /*
4110352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4111352f7f91STakashi Iwai  * Set up appropriately if really supported
4112352f7f91STakashi Iwai  */
4113352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4114352f7f91STakashi Iwai {
4115352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4116352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4117352f7f91STakashi Iwai 	int present = 0;
4118352f7f91STakashi Iwai 	int i, err;
4119352f7f91STakashi Iwai 
4120f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4121f72706beSTakashi Iwai 		return 0;
4122f72706beSTakashi Iwai 
4123352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4124352f7f91STakashi Iwai 		present++;
4125352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4126352f7f91STakashi Iwai 		present++;
4127352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4128352f7f91STakashi Iwai 		present++;
4129352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4130352f7f91STakashi Iwai 		return 0;
4131352f7f91STakashi Iwai 
4132352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4133352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4134352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4135352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4136352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4137352f7f91STakashi Iwai 	}
4138352f7f91STakashi Iwai 
4139352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4140352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4141352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4142352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4143352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4144352f7f91STakashi Iwai 	}
4145352f7f91STakashi Iwai 
4146352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4147352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4148352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4149352f7f91STakashi Iwai 			continue;
4150352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
4151352f7f91STakashi Iwai 			    nid);
4152352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
415377afe0e9STakashi Iwai 						    call_hp_automute);
4154352f7f91STakashi Iwai 		spec->detect_hp = 1;
4155352f7f91STakashi Iwai 	}
4156352f7f91STakashi Iwai 
4157352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4158352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4159352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4160352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4161352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4162352f7f91STakashi Iwai 					continue;
4163352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
4164352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
4165352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
416677afe0e9STakashi Iwai 								    call_line_automute);
4167352f7f91STakashi Iwai 				spec->detect_lo = 1;
4168352f7f91STakashi Iwai 			}
4169352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4170352f7f91STakashi Iwai 	}
4171352f7f91STakashi Iwai 
4172352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4173352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4174352f7f91STakashi Iwai 
4175352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4176352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4177352f7f91STakashi Iwai 
4178352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4179352f7f91STakashi Iwai 		/* create a control for automute mode */
4180352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4181352f7f91STakashi Iwai 		if (err < 0)
4182352f7f91STakashi Iwai 			return err;
4183352f7f91STakashi Iwai 	}
4184352f7f91STakashi Iwai 	return 0;
4185352f7f91STakashi Iwai }
4186352f7f91STakashi Iwai 
4187352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4188352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4189352f7f91STakashi Iwai {
4190352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4191352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4192352f7f91STakashi Iwai 	int i;
4193352f7f91STakashi Iwai 
4194352f7f91STakashi Iwai 	imux = &spec->input_mux;
4195352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4196352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4197352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4198352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4199352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4200352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4201352f7f91STakashi Iwai 	}
4202352f7f91STakashi Iwai 
4203352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4204352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4205352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4206352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
4207352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
420877afe0e9STakashi Iwai 						    call_mic_autoswitch);
4209352f7f91STakashi Iwai 	return true;
4210352f7f91STakashi Iwai }
4211352f7f91STakashi Iwai 
4212352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4213352f7f91STakashi Iwai {
4214352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4215352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4216352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4217352f7f91STakashi Iwai }
4218352f7f91STakashi Iwai 
4219352f7f91STakashi Iwai /*
4220352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4221352f7f91STakashi Iwai  * Set up if really supported
4222352f7f91STakashi Iwai  */
4223352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4224352f7f91STakashi Iwai {
4225352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4226352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4227352f7f91STakashi Iwai 	unsigned int types;
4228352f7f91STakashi Iwai 	int i, num_pins;
4229352f7f91STakashi Iwai 
4230d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4231d12daf6fSTakashi Iwai 		return 0;
4232d12daf6fSTakashi Iwai 
4233352f7f91STakashi Iwai 	types = 0;
4234352f7f91STakashi Iwai 	num_pins = 0;
4235352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4236352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4237352f7f91STakashi Iwai 		unsigned int attr;
4238352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4239352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4240352f7f91STakashi Iwai 		if (types & (1 << attr))
4241352f7f91STakashi Iwai 			return 0; /* already occupied */
4242352f7f91STakashi Iwai 		switch (attr) {
4243352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4244352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4245352f7f91STakashi Iwai 				return 0; /* invalid type */
4246352f7f91STakashi Iwai 			break;
4247352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4248352f7f91STakashi Iwai 			return 0; /* invalid entry */
4249352f7f91STakashi Iwai 		default:
4250352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4251352f7f91STakashi Iwai 				return 0; /* invalid type */
4252352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4253352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4254352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4255352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4256352f7f91STakashi Iwai 				return 0; /* no unsol support */
4257352f7f91STakashi Iwai 			break;
4258352f7f91STakashi Iwai 		}
4259352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4260352f7f91STakashi Iwai 			return 0;
4261352f7f91STakashi Iwai 		types |= (1 << attr);
4262352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4263352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4264352f7f91STakashi Iwai 		num_pins++;
4265352f7f91STakashi Iwai 	}
4266352f7f91STakashi Iwai 
4267352f7f91STakashi Iwai 	if (num_pins < 2)
4268352f7f91STakashi Iwai 		return 0;
4269352f7f91STakashi Iwai 
4270352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4271352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4272352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4273352f7f91STakashi Iwai 	 */
4274352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4275352f7f91STakashi Iwai 	     compare_attr, NULL);
4276352f7f91STakashi Iwai 
4277352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4278352f7f91STakashi Iwai 		return 0;
4279352f7f91STakashi Iwai 
4280352f7f91STakashi Iwai 	spec->auto_mic = 1;
4281352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4282352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
4283352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4284352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4285352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4286352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4287352f7f91STakashi Iwai 
4288352f7f91STakashi Iwai 	return 0;
4289352f7f91STakashi Iwai }
4290352f7f91STakashi Iwai 
429155196fffSTakashi Iwai /* power_filter hook; make inactive widgets into power down */
429255196fffSTakashi Iwai static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
429355196fffSTakashi Iwai 						  hda_nid_t nid,
429455196fffSTakashi Iwai 						  unsigned int power_state)
429555196fffSTakashi Iwai {
429655196fffSTakashi Iwai 	if (power_state != AC_PWRST_D0)
429755196fffSTakashi Iwai 		return power_state;
429855196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
429955196fffSTakashi Iwai 		return power_state;
4300b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
430155196fffSTakashi Iwai 		return power_state;
430255196fffSTakashi Iwai 	return AC_PWRST_D3;
430355196fffSTakashi Iwai }
430455196fffSTakashi Iwai 
4305352f7f91STakashi Iwai 
43069eb413e5STakashi Iwai /*
43079eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
43089eb413e5STakashi Iwai  *
43099eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4310352f7f91STakashi Iwai  * or a negative error code
4311352f7f91STakashi Iwai  */
4312352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
43139eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4314352f7f91STakashi Iwai {
4315352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4316352f7f91STakashi Iwai 	int err;
4317352f7f91STakashi Iwai 
43181c70a583STakashi Iwai 	parse_user_hints(codec);
43191c70a583STakashi Iwai 
4320e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4321e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4322e4a395e7STakashi Iwai 
43239eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
43249eb413e5STakashi Iwai 		spec->autocfg = *cfg;
43259eb413e5STakashi Iwai 		cfg = &spec->autocfg;
43269eb413e5STakashi Iwai 	}
43279eb413e5STakashi Iwai 
432898bd1115STakashi Iwai 	if (!spec->main_out_badness)
432998bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
433098bd1115STakashi Iwai 	if (!spec->extra_out_badness)
433198bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
433298bd1115STakashi Iwai 
43336fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
43346fc4cb97SDavid Henningsson 
4335352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4336352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4337352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4338352f7f91STakashi Iwai 			spec->no_analog = 1;
4339352f7f91STakashi Iwai 			goto dig_only;
4340352f7f91STakashi Iwai 		}
4341c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4342352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4343352f7f91STakashi Iwai 	}
4344352f7f91STakashi Iwai 
4345352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4346352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4347352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4348352f7f91STakashi Iwai 		/* use HP as primary out */
4349352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4350352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4351352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4352352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4353352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4354352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4355352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4356352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4357352f7f91STakashi Iwai 	}
4358352f7f91STakashi Iwai 
4359352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4360352f7f91STakashi Iwai 	if (err < 0)
4361352f7f91STakashi Iwai 		return err;
4362352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4363352f7f91STakashi Iwai 	if (err < 0)
4364352f7f91STakashi Iwai 		return err;
4365352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4366352f7f91STakashi Iwai 	if (err < 0)
4367352f7f91STakashi Iwai 		return err;
4368352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4369352f7f91STakashi Iwai 	if (err < 0)
4370352f7f91STakashi Iwai 		return err;
4371352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4372352f7f91STakashi Iwai 	if (err < 0)
4373352f7f91STakashi Iwai 		return err;
437438cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
437538cf6f1aSTakashi Iwai 	if (err < 0)
437638cf6f1aSTakashi Iwai 		return err;
4377c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4378c30aa7b2STakashi Iwai 	if (err < 0)
4379c30aa7b2STakashi Iwai 		return err;
4380967303daSTakashi Iwai 	err = create_hp_mic(codec);
4381352f7f91STakashi Iwai 	if (err < 0)
4382352f7f91STakashi Iwai 		return err;
4383352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4384352f7f91STakashi Iwai 	if (err < 0)
4385352f7f91STakashi Iwai 		return err;
4386352f7f91STakashi Iwai 
4387a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4388a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4389a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4390a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4391a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4392a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4393a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4394a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4395352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4396352f7f91STakashi Iwai 					  spec->const_channel_count);
4397352f7f91STakashi Iwai 
4398352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4399352f7f91STakashi Iwai 	if (err < 0)
4400352f7f91STakashi Iwai 		return err;
4401352f7f91STakashi Iwai 
4402352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4403352f7f91STakashi Iwai 	if (err < 0)
4404352f7f91STakashi Iwai 		return err;
4405352f7f91STakashi Iwai 
4406352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4407352f7f91STakashi Iwai 	if (err < 0)
4408352f7f91STakashi Iwai 		return err;
4409352f7f91STakashi Iwai 
4410f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
4411f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
4412f1e762ddSTakashi Iwai 	    spec->add_stereo_mix_input &&
4413f1e762ddSTakashi Iwai 	    spec->input_mux.num_items > 1 &&
4414f1e762ddSTakashi Iwai 	    snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
4415f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
4416f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
4417f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
4418f1e762ddSTakashi Iwai 		if (err < 0)
4419f1e762ddSTakashi Iwai 			return err;
4420f1e762ddSTakashi Iwai 	}
4421f1e762ddSTakashi Iwai 
4422f1e762ddSTakashi Iwai 
4423352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4424352f7f91STakashi Iwai 	if (err < 0)
4425352f7f91STakashi Iwai 		return err;
4426352f7f91STakashi Iwai 
4427352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4428352f7f91STakashi Iwai 	if (err < 0)
4429352f7f91STakashi Iwai 		return err;
4430352f7f91STakashi Iwai 
4431ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4432ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4433ced4cefcSTakashi Iwai 	 */
4434ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4435ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4436ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4437ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4438ced4cefcSTakashi Iwai 		if (err < 0)
4439ced4cefcSTakashi Iwai 			return err;
4440ced4cefcSTakashi Iwai 	}
4441ced4cefcSTakashi Iwai 
4442f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4443978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4444978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4445978e77e7STakashi Iwai 						    cfg->line_out_pins);
4446978e77e7STakashi Iwai 			if (err < 0)
4447978e77e7STakashi Iwai 				return err;
4448978e77e7STakashi Iwai 		}
4449978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4450978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4451978e77e7STakashi Iwai 						    cfg->hp_pins);
4452978e77e7STakashi Iwai 			if (err < 0)
4453978e77e7STakashi Iwai 				return err;
4454978e77e7STakashi Iwai 		}
4455978e77e7STakashi Iwai 	}
4456978e77e7STakashi Iwai 
4457352f7f91STakashi Iwai  dig_only:
4458352f7f91STakashi Iwai 	parse_digital(codec);
4459352f7f91STakashi Iwai 
446055196fffSTakashi Iwai 	if (spec->power_down_unused)
446155196fffSTakashi Iwai 		codec->power_filter = snd_hda_gen_path_power_filter;
446255196fffSTakashi Iwai 
44637504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
44647504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
44657504b6cdSTakashi Iwai 		if (err < 0)
44667504b6cdSTakashi Iwai 			return err;
44677504b6cdSTakashi Iwai 	}
44687504b6cdSTakashi Iwai 
4469352f7f91STakashi Iwai 	return 1;
4470352f7f91STakashi Iwai }
4471352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
4472352f7f91STakashi Iwai 
4473352f7f91STakashi Iwai 
4474352f7f91STakashi Iwai /*
4475352f7f91STakashi Iwai  * Build control elements
4476352f7f91STakashi Iwai  */
4477352f7f91STakashi Iwai 
4478352f7f91STakashi Iwai /* slave controls for virtual master */
4479352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4480352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4481352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4482352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4483ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4484ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
4485ee79c69aSTakashi Iwai 	"Headphone Side",
4486352f7f91STakashi Iwai 	NULL,
4487352f7f91STakashi Iwai };
4488352f7f91STakashi Iwai 
4489352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
4490352f7f91STakashi Iwai {
4491352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4492352f7f91STakashi Iwai 	int err;
4493352f7f91STakashi Iwai 
449436502d02STakashi Iwai 	if (spec->kctls.used) {
4495352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
4496352f7f91STakashi Iwai 		if (err < 0)
4497352f7f91STakashi Iwai 			return err;
449836502d02STakashi Iwai 	}
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
4501352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
4502352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4503352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4504352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
4505352f7f91STakashi Iwai 		if (err < 0)
4506352f7f91STakashi Iwai 			return err;
4507352f7f91STakashi Iwai 		if (!spec->no_analog) {
4508352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
4509352f7f91STakashi Iwai 							    &spec->multiout);
4510352f7f91STakashi Iwai 			if (err < 0)
4511352f7f91STakashi Iwai 				return err;
4512352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
4513352f7f91STakashi Iwai 		}
4514352f7f91STakashi Iwai 	}
4515352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
4516352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
4517352f7f91STakashi Iwai 		if (err < 0)
4518352f7f91STakashi Iwai 			return err;
4519352f7f91STakashi Iwai 	}
4520352f7f91STakashi Iwai 
4521352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
4522352f7f91STakashi Iwai 	if (!spec->no_analog &&
4523352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
4524352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
45257a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
4526352f7f91STakashi Iwai 					  "Playback Volume");
4527352f7f91STakashi Iwai 		if (err < 0)
4528352f7f91STakashi Iwai 			return err;
4529352f7f91STakashi Iwai 	}
4530352f7f91STakashi Iwai 	if (!spec->no_analog &&
4531352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
4532352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
4533352f7f91STakashi Iwai 					    NULL, slave_pfxs,
4534352f7f91STakashi Iwai 					    "Playback Switch",
4535352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
4536352f7f91STakashi Iwai 		if (err < 0)
4537352f7f91STakashi Iwai 			return err;
4538b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
4539fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
4540fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
4541b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4542b63eae0aSTakashi Iwai 		}
4543352f7f91STakashi Iwai 	}
4544352f7f91STakashi Iwai 
4545352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
4546352f7f91STakashi Iwai 
4547352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
4548352f7f91STakashi Iwai 	if (err < 0)
4549352f7f91STakashi Iwai 		return err;
4550352f7f91STakashi Iwai 
4551352f7f91STakashi Iwai 	return 0;
4552352f7f91STakashi Iwai }
4553352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
4554352f7f91STakashi Iwai 
4555352f7f91STakashi Iwai 
4556352f7f91STakashi Iwai /*
4557352f7f91STakashi Iwai  * PCM definitions
4558352f7f91STakashi Iwai  */
4559352f7f91STakashi Iwai 
4560e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
4561e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
4562e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
4563e6b85f3cSTakashi Iwai 				   int action)
4564e6b85f3cSTakashi Iwai {
4565e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4566e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
4567e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
4568e6b85f3cSTakashi Iwai }
4569e6b85f3cSTakashi Iwai 
4570ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
4571ac2e8736STakashi Iwai 				  struct hda_codec *codec,
4572ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
4573ac2e8736STakashi Iwai 				  int action)
4574ac2e8736STakashi Iwai {
4575ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4576ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
4577ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
4578ac2e8736STakashi Iwai }
4579ac2e8736STakashi Iwai 
4580352f7f91STakashi Iwai /*
4581352f7f91STakashi Iwai  * Analog playback callbacks
4582352f7f91STakashi Iwai  */
4583352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
4584352f7f91STakashi Iwai 			     struct hda_codec *codec,
4585352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
4586352f7f91STakashi Iwai {
4587352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
458838cf6f1aSTakashi Iwai 	int err;
458938cf6f1aSTakashi Iwai 
459038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
459138cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
459238cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
4593352f7f91STakashi Iwai 					     hinfo);
4594e6b85f3cSTakashi Iwai 	if (!err) {
459538cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
4596e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4597e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
4598e6b85f3cSTakashi Iwai 	}
459938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
460038cf6f1aSTakashi Iwai 	return err;
4601352f7f91STakashi Iwai }
4602352f7f91STakashi Iwai 
4603352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
460497ec558aSTakashi Iwai 				struct hda_codec *codec,
460597ec558aSTakashi Iwai 				unsigned int stream_tag,
460697ec558aSTakashi Iwai 				unsigned int format,
460797ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
460897ec558aSTakashi Iwai {
4609352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4610e6b85f3cSTakashi Iwai 	int err;
4611e6b85f3cSTakashi Iwai 
4612e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4613352f7f91STakashi Iwai 					       stream_tag, format, substream);
4614e6b85f3cSTakashi Iwai 	if (!err)
4615e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4616e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4617e6b85f3cSTakashi Iwai 	return err;
4618352f7f91STakashi Iwai }
461997ec558aSTakashi Iwai 
4620352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4621352f7f91STakashi Iwai 				struct hda_codec *codec,
4622352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4623352f7f91STakashi Iwai {
4624352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4625e6b85f3cSTakashi Iwai 	int err;
4626e6b85f3cSTakashi Iwai 
4627e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4628e6b85f3cSTakashi Iwai 	if (!err)
4629e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4630e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4631e6b85f3cSTakashi Iwai 	return err;
4632352f7f91STakashi Iwai }
4633352f7f91STakashi Iwai 
463438cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
463538cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
463638cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
463738cf6f1aSTakashi Iwai {
463838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
463938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
464038cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4641e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4642e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
464338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
464438cf6f1aSTakashi Iwai 	return 0;
464538cf6f1aSTakashi Iwai }
464638cf6f1aSTakashi Iwai 
4647ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4648ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4649ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4650ac2e8736STakashi Iwai {
4651ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4652ac2e8736STakashi Iwai 	return 0;
4653ac2e8736STakashi Iwai }
4654ac2e8736STakashi Iwai 
4655ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4656ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4657ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4658ac2e8736STakashi Iwai 			       unsigned int format,
4659ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4660ac2e8736STakashi Iwai {
4661ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4662ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4663ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4664ac2e8736STakashi Iwai 	return 0;
4665ac2e8736STakashi Iwai }
4666ac2e8736STakashi Iwai 
4667ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4668ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4669ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4670ac2e8736STakashi Iwai {
4671ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4672ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4673ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4674ac2e8736STakashi Iwai 	return 0;
4675ac2e8736STakashi Iwai }
4676ac2e8736STakashi Iwai 
4677ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4678ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4679ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4680ac2e8736STakashi Iwai {
4681ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4682ac2e8736STakashi Iwai 	return 0;
4683ac2e8736STakashi Iwai }
4684ac2e8736STakashi Iwai 
468538cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
468638cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
468738cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
468838cf6f1aSTakashi Iwai {
468938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
469038cf6f1aSTakashi Iwai 	int err = 0;
469138cf6f1aSTakashi Iwai 
469238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
469338cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
469438cf6f1aSTakashi Iwai 		err = -EBUSY;
469538cf6f1aSTakashi Iwai 	else
469638cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4697e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4698e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
469938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
470038cf6f1aSTakashi Iwai 	return err;
470138cf6f1aSTakashi Iwai }
470238cf6f1aSTakashi Iwai 
470338cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
470438cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
470538cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
470638cf6f1aSTakashi Iwai {
470738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
470838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
470938cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4710e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4711e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
471238cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
471338cf6f1aSTakashi Iwai 	return 0;
471438cf6f1aSTakashi Iwai }
471538cf6f1aSTakashi Iwai 
4716e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4717e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4718e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4719e6b85f3cSTakashi Iwai 				    unsigned int format,
4720e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4721e6b85f3cSTakashi Iwai {
4722e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4723e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4724e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4725e6b85f3cSTakashi Iwai 	return 0;
4726e6b85f3cSTakashi Iwai }
4727e6b85f3cSTakashi Iwai 
4728e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4729e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4730e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4731e6b85f3cSTakashi Iwai {
4732e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4733e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4734e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4735e6b85f3cSTakashi Iwai 	return 0;
4736e6b85f3cSTakashi Iwai }
4737e6b85f3cSTakashi Iwai 
4738352f7f91STakashi Iwai /*
4739352f7f91STakashi Iwai  * Digital out
4740352f7f91STakashi Iwai  */
4741352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4742352f7f91STakashi Iwai 				 struct hda_codec *codec,
4743352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4744352f7f91STakashi Iwai {
4745352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4746352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4747352f7f91STakashi Iwai }
4748352f7f91STakashi Iwai 
4749352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4750352f7f91STakashi Iwai 				    struct hda_codec *codec,
4751352f7f91STakashi Iwai 				    unsigned int stream_tag,
4752352f7f91STakashi Iwai 				    unsigned int format,
4753352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4754352f7f91STakashi Iwai {
4755352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4756352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4757352f7f91STakashi Iwai 					     stream_tag, format, substream);
4758352f7f91STakashi Iwai }
4759352f7f91STakashi Iwai 
4760352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4761352f7f91STakashi Iwai 				    struct hda_codec *codec,
4762352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4763352f7f91STakashi Iwai {
4764352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4765352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4766352f7f91STakashi Iwai }
4767352f7f91STakashi Iwai 
4768352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4769352f7f91STakashi Iwai 				  struct hda_codec *codec,
4770352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4771352f7f91STakashi Iwai {
4772352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4773352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4774352f7f91STakashi Iwai }
4775352f7f91STakashi Iwai 
4776352f7f91STakashi Iwai /*
4777352f7f91STakashi Iwai  * Analog capture
4778352f7f91STakashi Iwai  */
4779ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4780ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4781ac2e8736STakashi Iwai 
4782352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4783352f7f91STakashi Iwai 				   struct hda_codec *codec,
4784352f7f91STakashi Iwai 				   unsigned int stream_tag,
4785352f7f91STakashi Iwai 				   unsigned int format,
4786352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4787352f7f91STakashi Iwai {
4788352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4789352f7f91STakashi Iwai 
4790352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
479197ec558aSTakashi Iwai 				   stream_tag, 0, format);
4792ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4793ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
479497ec558aSTakashi Iwai 	return 0;
479597ec558aSTakashi Iwai }
479697ec558aSTakashi Iwai 
4797352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
479897ec558aSTakashi Iwai 				   struct hda_codec *codec,
479997ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
480097ec558aSTakashi Iwai {
4801352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
480297ec558aSTakashi Iwai 
4803352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4804352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4805ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4806ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
480797ec558aSTakashi Iwai 	return 0;
480897ec558aSTakashi Iwai }
480997ec558aSTakashi Iwai 
4810352f7f91STakashi Iwai /*
4811352f7f91STakashi Iwai  */
4812352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4813352f7f91STakashi Iwai 	.substreams = 1,
4814352f7f91STakashi Iwai 	.channels_min = 2,
4815352f7f91STakashi Iwai 	.channels_max = 8,
4816352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4817352f7f91STakashi Iwai 	.ops = {
4818352f7f91STakashi Iwai 		.open = playback_pcm_open,
481938cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4820352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4821352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4822352f7f91STakashi Iwai 	},
4823352f7f91STakashi Iwai };
4824352f7f91STakashi Iwai 
4825352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4826352f7f91STakashi Iwai 	.substreams = 1,
4827352f7f91STakashi Iwai 	.channels_min = 2,
4828352f7f91STakashi Iwai 	.channels_max = 2,
4829352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4830ac2e8736STakashi Iwai 	.ops = {
4831ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4832ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4833ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4834ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4835ac2e8736STakashi Iwai 	},
4836352f7f91STakashi Iwai };
4837352f7f91STakashi Iwai 
4838352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4839352f7f91STakashi Iwai 	.substreams = 1,
4840352f7f91STakashi Iwai 	.channels_min = 2,
4841352f7f91STakashi Iwai 	.channels_max = 2,
4842352f7f91STakashi Iwai 	/* NID is set in build_pcms */
484338cf6f1aSTakashi Iwai 	.ops = {
484438cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4845e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4846e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4847e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
484838cf6f1aSTakashi Iwai 	},
4849352f7f91STakashi Iwai };
4850352f7f91STakashi Iwai 
4851352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4852352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4853352f7f91STakashi Iwai 	.channels_min = 2,
4854352f7f91STakashi Iwai 	.channels_max = 2,
4855352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4856352f7f91STakashi Iwai 	.ops = {
4857ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4858ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4859352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4860352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4861352f7f91STakashi Iwai 	},
4862352f7f91STakashi Iwai };
4863352f7f91STakashi Iwai 
4864352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4865352f7f91STakashi Iwai 	.substreams = 1,
4866352f7f91STakashi Iwai 	.channels_min = 2,
4867352f7f91STakashi Iwai 	.channels_max = 2,
4868352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4869352f7f91STakashi Iwai 	.ops = {
4870352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4871352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4872352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4873352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4874352f7f91STakashi Iwai 	},
4875352f7f91STakashi Iwai };
4876352f7f91STakashi Iwai 
4877352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4878352f7f91STakashi Iwai 	.substreams = 1,
4879352f7f91STakashi Iwai 	.channels_min = 2,
4880352f7f91STakashi Iwai 	.channels_max = 2,
4881352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4882352f7f91STakashi Iwai };
4883352f7f91STakashi Iwai 
4884352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4885352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4886352f7f91STakashi Iwai 	.substreams = 0,
4887352f7f91STakashi Iwai 	.channels_min = 0,
4888352f7f91STakashi Iwai 	.channels_max = 0,
4889352f7f91STakashi Iwai };
4890352f7f91STakashi Iwai 
4891352f7f91STakashi Iwai /*
4892352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4893352f7f91STakashi Iwai  */
4894352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
48951da177e4SLinus Torvalds {
4896352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4897352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
48981da177e4SLinus Torvalds 
4899352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4900352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4901352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4902352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4903352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4904352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4905352f7f91STakashi Iwai 					   spec->cur_adc_format);
4906352f7f91STakashi Iwai 		return true;
4907352f7f91STakashi Iwai 	}
4908352f7f91STakashi Iwai 	return false;
4909352f7f91STakashi Iwai }
4910352f7f91STakashi Iwai 
4911352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4912352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4913352f7f91STakashi Iwai 				       struct hda_codec *codec,
4914352f7f91STakashi Iwai 				       unsigned int stream_tag,
4915352f7f91STakashi Iwai 				       unsigned int format,
4916352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4917352f7f91STakashi Iwai {
4918352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4919352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4920352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4921352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4922352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
49231da177e4SLinus Torvalds 	return 0;
49241da177e4SLinus Torvalds }
49251da177e4SLinus Torvalds 
4926352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4927352f7f91STakashi Iwai 				       struct hda_codec *codec,
4928352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4929352f7f91STakashi Iwai {
4930352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4931352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4932352f7f91STakashi Iwai 	spec->cur_adc = 0;
4933352f7f91STakashi Iwai 	return 0;
4934352f7f91STakashi Iwai }
4935352f7f91STakashi Iwai 
4936352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4937352f7f91STakashi Iwai 	.substreams = 1,
4938352f7f91STakashi Iwai 	.channels_min = 2,
4939352f7f91STakashi Iwai 	.channels_max = 2,
4940352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4941352f7f91STakashi Iwai 	.ops = {
4942352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4943352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4944352f7f91STakashi Iwai 	},
4945352f7f91STakashi Iwai };
4946352f7f91STakashi Iwai 
4947f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4948f873e536STakashi Iwai 				 const char *chip_name)
4949f873e536STakashi Iwai {
4950f873e536STakashi Iwai 	char *p;
4951f873e536STakashi Iwai 
4952f873e536STakashi Iwai 	if (*str)
4953f873e536STakashi Iwai 		return;
4954f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4955f873e536STakashi Iwai 
4956f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4957f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4958f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4959f873e536STakashi Iwai 			*p = 0;
4960f873e536STakashi Iwai 			break;
4961f873e536STakashi Iwai 		}
4962f873e536STakashi Iwai 	}
4963f873e536STakashi Iwai 	strlcat(str, sfx, len);
4964f873e536STakashi Iwai }
4965f873e536STakashi Iwai 
4966352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4967352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4968352f7f91STakashi Iwai {
4969352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4970352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4971352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4972352f7f91STakashi Iwai 	bool have_multi_adcs;
4973352f7f91STakashi Iwai 
49741da177e4SLinus Torvalds 	codec->num_pcms = 1;
49751da177e4SLinus Torvalds 	codec->pcm_info = info;
49761da177e4SLinus Torvalds 
4977352f7f91STakashi Iwai 	if (spec->no_analog)
4978352f7f91STakashi Iwai 		goto skip_analog;
4979352f7f91STakashi Iwai 
4980f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
4981f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
4982f873e536STakashi Iwai 			     " Analog", codec->chip_name);
4983352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
4984352f7f91STakashi Iwai 
4985352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
4986352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
4987352f7f91STakashi Iwai 		if (!p)
4988352f7f91STakashi Iwai 			p = &pcm_analog_playback;
4989352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4990352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4991352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
4992352f7f91STakashi Iwai 			spec->multiout.max_channels;
4993352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
4994352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
4995352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
4996352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
4997352f7f91STakashi Iwai 	}
4998352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
4999352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
5000352f7f91STakashi Iwai 		if (!p) {
5001352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
5002352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
5003352f7f91STakashi Iwai 			else
5004352f7f91STakashi Iwai 				p = &pcm_analog_capture;
5005352f7f91STakashi Iwai 		}
5006352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5007352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
5008352f7f91STakashi Iwai 	}
5009352f7f91STakashi Iwai 
5010352f7f91STakashi Iwai  skip_analog:
5011352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5012352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5013f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5014352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
5015f873e536STakashi Iwai 				     " Digital", codec->chip_name);
5016352f7f91STakashi Iwai 		codec->num_pcms = 2;
5017352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5018352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
5019352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
5020352f7f91STakashi Iwai 		if (spec->dig_out_type)
5021352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5022352f7f91STakashi Iwai 		else
5023352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5024352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
5025352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
5026352f7f91STakashi Iwai 			if (!p)
5027352f7f91STakashi Iwai 				p = &pcm_digital_playback;
5028352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5029352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
5030352f7f91STakashi Iwai 		}
5031352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
5032352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
5033352f7f91STakashi Iwai 			if (!p)
5034352f7f91STakashi Iwai 				p = &pcm_digital_capture;
5035352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5036352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
5037352f7f91STakashi Iwai 		}
5038352f7f91STakashi Iwai 	}
5039352f7f91STakashi Iwai 
5040352f7f91STakashi Iwai 	if (spec->no_analog)
5041352f7f91STakashi Iwai 		return 0;
5042352f7f91STakashi Iwai 
5043352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5044352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5045352f7f91STakashi Iwai 	 */
5046352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5047352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5048352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5049352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5050a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5051a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
5052a607148fSTakashi Iwai 			     " Alt Analog", codec->chip_name);
5053352f7f91STakashi Iwai 		codec->num_pcms = 3;
5054352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
5055a607148fSTakashi Iwai 		info->name = spec->stream_name_alt_analog;
5056352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
5057352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
5058352f7f91STakashi Iwai 			if (!p)
5059352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
5060352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5061352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
5062352f7f91STakashi Iwai 				spec->alt_dac_nid;
5063352f7f91STakashi Iwai 		} else {
5064352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
5065352f7f91STakashi Iwai 				pcm_null_stream;
5066352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
5067352f7f91STakashi Iwai 		}
5068352f7f91STakashi Iwai 		if (have_multi_adcs) {
5069352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
5070352f7f91STakashi Iwai 			if (!p)
5071352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
5072352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5073352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
5074352f7f91STakashi Iwai 				spec->adc_nids[1];
5075352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5076352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5077352f7f91STakashi Iwai 		} else {
5078352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
5079352f7f91STakashi Iwai 				pcm_null_stream;
5080352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
5081352f7f91STakashi Iwai 		}
50821da177e4SLinus Torvalds 	}
50831da177e4SLinus Torvalds 
50841da177e4SLinus Torvalds 	return 0;
50851da177e4SLinus Torvalds }
5086352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
5087352f7f91STakashi Iwai 
5088352f7f91STakashi Iwai 
5089352f7f91STakashi Iwai /*
5090352f7f91STakashi Iwai  * Standard auto-parser initializations
5091352f7f91STakashi Iwai  */
5092352f7f91STakashi Iwai 
5093d4156930STakashi Iwai /* configure the given path as a proper output */
50942c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5095352f7f91STakashi Iwai {
5096352f7f91STakashi Iwai 	struct nid_path *path;
5097d4156930STakashi Iwai 	hda_nid_t pin;
5098352f7f91STakashi Iwai 
5099196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5100d4156930STakashi Iwai 	if (!path || !path->depth)
5101352f7f91STakashi Iwai 		return;
5102d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
51032c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
510465033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
510565033cc8STakashi Iwai 			      aamix_default(codec->spec));
5106e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5107352f7f91STakashi Iwai }
5108352f7f91STakashi Iwai 
5109352f7f91STakashi Iwai /* initialize primary output paths */
5110352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5111352f7f91STakashi Iwai {
5112352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5113352f7f91STakashi Iwai 	int i;
5114352f7f91STakashi Iwai 
5115d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
51162c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5117352f7f91STakashi Iwai }
5118352f7f91STakashi Iwai 
5119db23fd19STakashi Iwai 
51202c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5121352f7f91STakashi Iwai {
5122352f7f91STakashi Iwai 	int i;
5123352f7f91STakashi Iwai 
5124d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
51252c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5126352f7f91STakashi Iwai }
5127db23fd19STakashi Iwai 
5128db23fd19STakashi Iwai /* initialize hp and speaker paths */
5129db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5130db23fd19STakashi Iwai {
5131db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5132db23fd19STakashi Iwai 
5133db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
51342c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5135db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5136db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
51372c12c30dSTakashi Iwai 				 spec->speaker_paths);
5138352f7f91STakashi Iwai }
5139352f7f91STakashi Iwai 
5140352f7f91STakashi Iwai /* initialize multi-io paths */
5141352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5142352f7f91STakashi Iwai {
5143352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5144352f7f91STakashi Iwai 	int i;
5145352f7f91STakashi Iwai 
5146352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5147352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5148352f7f91STakashi Iwai 		struct nid_path *path;
5149196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5150352f7f91STakashi Iwai 		if (!path)
5151352f7f91STakashi Iwai 			continue;
5152352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5153352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
51542c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
515565033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
515665033cc8STakashi Iwai 				      aamix_default(spec));
5157352f7f91STakashi Iwai 	}
5158352f7f91STakashi Iwai }
5159352f7f91STakashi Iwai 
51604f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
51614f7f67fbSTakashi Iwai {
51624f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
51634f7f67fbSTakashi Iwai 
51644f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
51654f7f67fbSTakashi Iwai 		return;
51664f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
51674f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
51684f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
51694f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
51704f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
51714f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
51724f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
51734f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
51744f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
51754f7f67fbSTakashi Iwai }
51764f7f67fbSTakashi Iwai 
5177352f7f91STakashi Iwai /* set up input pins and loopback paths */
5178352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5179352f7f91STakashi Iwai {
5180352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5181352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5182352f7f91STakashi Iwai 	int i;
5183352f7f91STakashi Iwai 
5184352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5185352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5186352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
51872c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5188352f7f91STakashi Iwai 
5189352f7f91STakashi Iwai 		/* init loopback inputs */
5190352f7f91STakashi Iwai 		if (spec->mixer_nid) {
51913e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
51923e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5193352f7f91STakashi Iwai 		}
5194352f7f91STakashi Iwai 	}
5195352f7f91STakashi Iwai }
5196352f7f91STakashi Iwai 
5197352f7f91STakashi Iwai /* initialize ADC paths */
5198352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5199352f7f91STakashi Iwai {
5200352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5201352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5202352f7f91STakashi Iwai 	struct nid_path *path;
5203352f7f91STakashi Iwai 	int i, c, nums;
5204352f7f91STakashi Iwai 
5205352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5206352f7f91STakashi Iwai 		nums = 1;
5207352f7f91STakashi Iwai 	else
5208352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5209352f7f91STakashi Iwai 
5210352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5211352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5212c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5213352f7f91STakashi Iwai 			if (path) {
5214352f7f91STakashi Iwai 				bool active = path->active;
5215352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5216352f7f91STakashi Iwai 					active = true;
5217352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5218352f7f91STakashi Iwai 			}
5219352f7f91STakashi Iwai 		}
5220967303daSTakashi Iwai 		if (spec->hp_mic)
5221967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5222352f7f91STakashi Iwai 	}
5223352f7f91STakashi Iwai 
5224352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
5225a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
5226352f7f91STakashi Iwai }
5227352f7f91STakashi Iwai 
5228352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5229352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5230352f7f91STakashi Iwai {
5231352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5232352f7f91STakashi Iwai 	int i;
5233352f7f91STakashi Iwai 	hda_nid_t pin;
5234352f7f91STakashi Iwai 
5235d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
52362c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5237352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
52382430d7b7STakashi Iwai 	if (pin) {
52392c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
52403e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
52412430d7b7STakashi Iwai 	}
5242352f7f91STakashi Iwai }
5243352f7f91STakashi Iwai 
5244973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5245973e4972STakashi Iwai  * invalid unsol tags by some reason
5246973e4972STakashi Iwai  */
5247973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5248973e4972STakashi Iwai {
5249973e4972STakashi Iwai 	int i;
5250973e4972STakashi Iwai 
5251973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5252973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5253973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5254973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5255973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5256973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5257973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5258973e4972STakashi Iwai 	}
5259973e4972STakashi Iwai }
5260973e4972STakashi Iwai 
52615187ac16STakashi Iwai /*
52625187ac16STakashi Iwai  * initialize the generic spec;
52635187ac16STakashi Iwai  * this can be put as patch_ops.init function
52645187ac16STakashi Iwai  */
5265352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5266352f7f91STakashi Iwai {
5267352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5268352f7f91STakashi Iwai 
5269352f7f91STakashi Iwai 	if (spec->init_hook)
5270352f7f91STakashi Iwai 		spec->init_hook(codec);
5271352f7f91STakashi Iwai 
5272352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5273352f7f91STakashi Iwai 
52743bbcd274STakashi Iwai 	codec->cached_write = 1;
52753bbcd274STakashi Iwai 
5276352f7f91STakashi Iwai 	init_multi_out(codec);
5277352f7f91STakashi Iwai 	init_extra_out(codec);
5278352f7f91STakashi Iwai 	init_multi_io(codec);
52794f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5280352f7f91STakashi Iwai 	init_analog_input(codec);
5281352f7f91STakashi Iwai 	init_input_src(codec);
5282352f7f91STakashi Iwai 	init_digital(codec);
5283352f7f91STakashi Iwai 
5284973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5285973e4972STakashi Iwai 
5286352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5287a5cc2509STakashi Iwai 	update_automute_all(codec);
5288352f7f91STakashi Iwai 
5289dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec);
52903bbcd274STakashi Iwai 
5291352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5292352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5293352f7f91STakashi Iwai 
5294352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5295352f7f91STakashi Iwai 	return 0;
5296352f7f91STakashi Iwai }
5297fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
5298fce52a3bSTakashi Iwai 
52995187ac16STakashi Iwai /*
53005187ac16STakashi Iwai  * free the generic spec;
53015187ac16STakashi Iwai  * this can be put as patch_ops.free function
53025187ac16STakashi Iwai  */
5303fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5304fce52a3bSTakashi Iwai {
53057504b6cdSTakashi Iwai 	snd_hda_detach_beep_device(codec);
5306fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5307fce52a3bSTakashi Iwai 	kfree(codec->spec);
5308fce52a3bSTakashi Iwai 	codec->spec = NULL;
5309fce52a3bSTakashi Iwai }
5310fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
5311fce52a3bSTakashi Iwai 
5312fce52a3bSTakashi Iwai #ifdef CONFIG_PM
53135187ac16STakashi Iwai /*
53145187ac16STakashi Iwai  * check the loopback power save state;
53155187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
53165187ac16STakashi Iwai  */
5317fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5318fce52a3bSTakashi Iwai {
5319fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5320fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5321fce52a3bSTakashi Iwai }
5322fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
5323fce52a3bSTakashi Iwai #endif
5324352f7f91STakashi Iwai 
5325352f7f91STakashi Iwai 
5326352f7f91STakashi Iwai /*
5327352f7f91STakashi Iwai  * the generic codec support
5328352f7f91STakashi Iwai  */
53291da177e4SLinus Torvalds 
5330352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5331352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5332352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5333352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5334fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5335352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
533683012a7cSTakashi Iwai #ifdef CONFIG_PM
5337fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5338cb53c626STakashi Iwai #endif
53391da177e4SLinus Torvalds };
53401da177e4SLinus Torvalds 
53411da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
53421da177e4SLinus Torvalds {
5343352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
53441da177e4SLinus Torvalds 	int err;
53451da177e4SLinus Torvalds 
5346e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5347352f7f91STakashi Iwai 	if (!spec)
53481da177e4SLinus Torvalds 		return -ENOMEM;
5349352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
53501da177e4SLinus Torvalds 	codec->spec = spec;
53511da177e4SLinus Torvalds 
53529eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
53539eb413e5STakashi Iwai 	if (err < 0)
53549eb413e5STakashi Iwai 		return err;
53559eb413e5STakashi Iwai 
53569eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5357352f7f91STakashi Iwai 	if (err < 0)
53581da177e4SLinus Torvalds 		goto error;
53591da177e4SLinus Torvalds 
53601da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
53611da177e4SLinus Torvalds 	return 0;
53621da177e4SLinus Torvalds 
53631da177e4SLinus Torvalds error:
5364fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
53651da177e4SLinus Torvalds 	return err;
53661da177e4SLinus Torvalds }
5367fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
5368b21bdd0dSTakashi Iwai 
5369b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
5370b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
5371