xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 43a8e50a)
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 }
512698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
692698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
902698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
2702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
2882698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
2992698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
4362698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 }
4672698ea98STakashi Iwai EXPORT_SYMBOL_GPL(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 
4783690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
4793690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
4803690739bSTakashi Iwai {
4813690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4823690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
4833690739bSTakashi Iwai 
4843690739bSTakashi Iwai 	if (!list)
4853690739bSTakashi Iwai 		return 0;
4863690739bSTakashi Iwai 	for (; *list; list += 2)
4873690739bSTakashi Iwai 		if (*list == pin)
4883690739bSTakashi Iwai 			return list[1];
4893690739bSTakashi Iwai 	return 0;
4903690739bSTakashi Iwai }
4913690739bSTakashi Iwai 
492352f7f91STakashi Iwai /* look for an empty DAC slot */
493352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
494352f7f91STakashi Iwai 			      bool is_digital)
495352f7f91STakashi Iwai {
496352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
497352f7f91STakashi Iwai 	bool cap_digital;
498352f7f91STakashi Iwai 	int i;
499352f7f91STakashi Iwai 
500352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
501352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
502352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
503352f7f91STakashi Iwai 			continue;
504352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
505352f7f91STakashi Iwai 		if (is_digital != cap_digital)
506352f7f91STakashi Iwai 			continue;
507352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
508352f7f91STakashi Iwai 			return nid;
509352f7f91STakashi Iwai 	}
510352f7f91STakashi Iwai 	return 0;
511352f7f91STakashi Iwai }
512352f7f91STakashi Iwai 
513352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
514352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
515352f7f91STakashi Iwai {
516352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
517352f7f91STakashi Iwai 	val |= chs << 16;
518352f7f91STakashi Iwai 	return val;
519352f7f91STakashi Iwai }
520352f7f91STakashi Iwai 
521352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
522352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
523352f7f91STakashi Iwai 			   int dir, unsigned int bits)
524352f7f91STakashi Iwai {
525352f7f91STakashi Iwai 	if (!nid)
526352f7f91STakashi Iwai 		return false;
527352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
528352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
529352f7f91STakashi Iwai 			return true;
530352f7f91STakashi Iwai 	return false;
531352f7f91STakashi Iwai }
532352f7f91STakashi Iwai 
53399a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
53499a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
53599a5592dSDavid Henningsson {
53699a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
53799a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
53899a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
53999a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
54099a5592dSDavid Henningsson }
54199a5592dSDavid Henningsson 
542352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
543f69910ddSTakashi Iwai 	check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
544352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
545352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
546352f7f91STakashi Iwai 
547352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
548352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
549352f7f91STakashi Iwai 				       struct nid_path *path)
550352f7f91STakashi Iwai {
551352f7f91STakashi Iwai 	int i;
552352f7f91STakashi Iwai 
553352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
554352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
555352f7f91STakashi Iwai 			return path->path[i];
556352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
557352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
558352f7f91STakashi Iwai 			return path->path[i];
559352f7f91STakashi Iwai 	}
560352f7f91STakashi Iwai 	return 0;
561352f7f91STakashi Iwai }
562352f7f91STakashi Iwai 
563352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
564352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
565352f7f91STakashi Iwai 				      struct nid_path *path)
566352f7f91STakashi Iwai {
567a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
568352f7f91STakashi Iwai 	int i;
569352f7f91STakashi Iwai 
570352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
571a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
572a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
573a1114a8cSTakashi Iwai 			continue;
574a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
575a1114a8cSTakashi Iwai 			return nid;
576352f7f91STakashi Iwai 	}
577352f7f91STakashi Iwai 	return 0;
578352f7f91STakashi Iwai }
579352f7f91STakashi Iwai 
580352f7f91STakashi Iwai /*
581352f7f91STakashi Iwai  * path activation / deactivation
582352f7f91STakashi Iwai  */
583352f7f91STakashi Iwai 
584352f7f91STakashi Iwai /* can have the amp-in capability? */
585352f7f91STakashi Iwai static bool has_amp_in(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_IN_AMP))
592352f7f91STakashi Iwai 		return false;
593352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
594352f7f91STakashi Iwai 		return false;
595352f7f91STakashi Iwai 	return true;
596352f7f91STakashi Iwai }
597352f7f91STakashi Iwai 
598352f7f91STakashi Iwai /* can have the amp-out capability? */
599352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
600352f7f91STakashi Iwai {
601352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
602352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
603352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
604352f7f91STakashi Iwai 
605352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
606352f7f91STakashi Iwai 		return false;
607352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
608352f7f91STakashi Iwai 		return false;
609352f7f91STakashi Iwai 	return true;
610352f7f91STakashi Iwai }
611352f7f91STakashi Iwai 
612352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
613352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6147dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
615352f7f91STakashi Iwai {
616352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
617352f7f91STakashi Iwai 	int i, n;
618352f7f91STakashi Iwai 
619352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
620352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
621352f7f91STakashi Iwai 		if (!path->active)
622352f7f91STakashi Iwai 			continue;
623352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
624352f7f91STakashi Iwai 			if (path->path[i] == nid) {
625352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
626352f7f91STakashi Iwai 					return true;
627352f7f91STakashi Iwai 				break;
628352f7f91STakashi Iwai 			}
629352f7f91STakashi Iwai 		}
630352f7f91STakashi Iwai 	}
631352f7f91STakashi Iwai 	return false;
632352f7f91STakashi Iwai }
633352f7f91STakashi Iwai 
634b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
635b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
636b1b9fbd0STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, 0)
637b1b9fbd0STakashi Iwai 
638352f7f91STakashi Iwai /* get the default amp value for the target state */
639352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6408999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
641352f7f91STakashi Iwai {
642352f7f91STakashi Iwai 	unsigned int val = 0;
643352f7f91STakashi Iwai 
644352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
645352f7f91STakashi Iwai 		/* set to 0dB */
646352f7f91STakashi Iwai 		if (enable)
647352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
648352f7f91STakashi Iwai 	}
649f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
650352f7f91STakashi Iwai 		if (!enable)
651352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
652352f7f91STakashi Iwai 	}
653352f7f91STakashi Iwai 	return val;
654352f7f91STakashi Iwai }
655352f7f91STakashi Iwai 
656352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
657352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
658352f7f91STakashi Iwai {
6598999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6608999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
661352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
662352f7f91STakashi Iwai }
663352f7f91STakashi Iwai 
6648999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6658999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
6668999bf0aSTakashi Iwai  */
6678999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
6688999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
6698999bf0aSTakashi Iwai 					   unsigned int caps)
670352f7f91STakashi Iwai {
6718999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
6728999bf0aSTakashi Iwai 
673f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
6748999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
6758999bf0aSTakashi Iwai 			mask &= ~0x80;
6768999bf0aSTakashi Iwai 	}
6778999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
6788999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
6798999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
6808999bf0aSTakashi Iwai 			mask &= ~0x7f;
6818999bf0aSTakashi Iwai 	}
6828999bf0aSTakashi Iwai 	return mask;
6838999bf0aSTakashi Iwai }
6848999bf0aSTakashi Iwai 
6858999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
6868999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
6878999bf0aSTakashi Iwai {
6888999bf0aSTakashi Iwai 	unsigned int caps;
6898999bf0aSTakashi Iwai 	unsigned int mask, val;
6908999bf0aSTakashi Iwai 
6917dddf2aeSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
692352f7f91STakashi Iwai 		return;
6938999bf0aSTakashi Iwai 
6948999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
6958999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
6968999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
6978999bf0aSTakashi Iwai 	if (!mask)
6988999bf0aSTakashi Iwai 		return;
6998999bf0aSTakashi Iwai 
7008999bf0aSTakashi Iwai 	val &= mask;
7018999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
702352f7f91STakashi Iwai }
703352f7f91STakashi Iwai 
704352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
705352f7f91STakashi Iwai 			     int i, bool enable)
706352f7f91STakashi Iwai {
707352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
708352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
7098999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
710352f7f91STakashi Iwai }
711352f7f91STakashi Iwai 
712352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
713352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
714352f7f91STakashi Iwai {
715352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
716ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
717352f7f91STakashi Iwai 	int n, nums, idx;
718352f7f91STakashi Iwai 	int type;
719352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
720352f7f91STakashi Iwai 
721ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
722352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
723352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
724352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
725352f7f91STakashi Iwai 		nums = 1;
726352f7f91STakashi Iwai 		idx = 0;
727352f7f91STakashi Iwai 	} else
728352f7f91STakashi Iwai 		idx = path->idx[i];
729352f7f91STakashi Iwai 
730352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
731352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
732352f7f91STakashi Iwai 
733352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
734352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
735352f7f91STakashi Iwai 	 */
736352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
737e4a395e7STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
738352f7f91STakashi Iwai 			continue;
7398999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
740352f7f91STakashi Iwai 	}
741352f7f91STakashi Iwai }
742352f7f91STakashi Iwai 
743352f7f91STakashi Iwai /* activate or deactivate the given path
744352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
745352f7f91STakashi Iwai  */
746352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
747352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
748352f7f91STakashi Iwai {
74955196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
750352f7f91STakashi Iwai 	int i;
751352f7f91STakashi Iwai 
752352f7f91STakashi Iwai 	if (!enable)
753352f7f91STakashi Iwai 		path->active = false;
754352f7f91STakashi Iwai 
755352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
75655196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
75755196fffSTakashi Iwai 		if (enable && spec->power_down_unused) {
75855196fffSTakashi Iwai 			/* make sure the widget is powered up */
75955196fffSTakashi Iwai 			if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
76055196fffSTakashi Iwai 				snd_hda_codec_write(codec, nid, 0,
76155196fffSTakashi Iwai 						    AC_VERB_SET_POWER_STATE,
76255196fffSTakashi Iwai 						    AC_PWRST_D0);
76355196fffSTakashi Iwai 		}
764352f7f91STakashi Iwai 		if (enable && path->multi[i])
76555196fffSTakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
766352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
767352f7f91STakashi Iwai 					    path->idx[i]);
768352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
769352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
770352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
771352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
772352f7f91STakashi Iwai 	}
773352f7f91STakashi Iwai 
774352f7f91STakashi Iwai 	if (enable)
775352f7f91STakashi Iwai 		path->active = true;
776352f7f91STakashi Iwai }
7772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
778352f7f91STakashi Iwai 
77955196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
78055196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
78155196fffSTakashi Iwai {
78255196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
783868211dbSJiri Slaby 	bool changed = false;
78455196fffSTakashi Iwai 	int i;
78555196fffSTakashi Iwai 
78655196fffSTakashi Iwai 	if (!spec->power_down_unused || path->active)
78755196fffSTakashi Iwai 		return;
78855196fffSTakashi Iwai 
78955196fffSTakashi Iwai 	for (i = 0; i < path->depth; i++) {
79055196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
791b1b9fbd0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
792b1b9fbd0STakashi Iwai 		    !is_active_nid_for_any(codec, nid)) {
79355196fffSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
79455196fffSTakashi Iwai 					    AC_VERB_SET_POWER_STATE,
79555196fffSTakashi Iwai 					    AC_PWRST_D3);
79655196fffSTakashi Iwai 			changed = true;
79755196fffSTakashi Iwai 		}
79855196fffSTakashi Iwai 	}
79955196fffSTakashi Iwai 
80055196fffSTakashi Iwai 	if (changed) {
80155196fffSTakashi Iwai 		msleep(10);
80255196fffSTakashi Iwai 		snd_hda_codec_read(codec, path->path[0], 0,
80355196fffSTakashi Iwai 				   AC_VERB_GET_POWER_STATE, 0);
80455196fffSTakashi Iwai 	}
80555196fffSTakashi Iwai }
80655196fffSTakashi Iwai 
807d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
808d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
809d5a9f1bbSTakashi Iwai {
810d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
811d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
812d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
813d5a9f1bbSTakashi Iwai 		return;
81405909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
81505909d5cSTakashi Iwai 		return;
816468ac413STakashi Iwai 	if (codec->inv_eapd)
817468ac413STakashi Iwai 		enable = !enable;
818d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
819d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
820d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
821d5a9f1bbSTakashi Iwai }
822d5a9f1bbSTakashi Iwai 
8233e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
8243e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
8253e367f15STakashi Iwai {
8263e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
8273e367f15STakashi Iwai 	if (path)
8283e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
8293e367f15STakashi Iwai }
8303e367f15STakashi Iwai 
831352f7f91STakashi Iwai 
832352f7f91STakashi Iwai /*
833352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
834352f7f91STakashi Iwai  */
835352f7f91STakashi Iwai 
8367eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
8377eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
838bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
839bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
8407eebffd3STakashi Iwai 
841352f7f91STakashi Iwai enum {
842352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
843352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
844352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
845352f7f91STakashi Iwai };
846352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
847352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
8487eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
8497eebffd3STakashi Iwai 	{
8507eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8517eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
8527eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
8537eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
8547eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
8557eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
8567eebffd3STakashi Iwai 	},
857bc2eee29STakashi Iwai 	{
858bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
859bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
860bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
861bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
862bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
863bc2eee29STakashi Iwai 	},
864352f7f91STakashi Iwai };
865352f7f91STakashi Iwai 
866352f7f91STakashi Iwai /* add dynamic controls from template */
867a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
868a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
869352f7f91STakashi Iwai 		       int cidx, unsigned long val)
870352f7f91STakashi Iwai {
871352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
872352f7f91STakashi Iwai 
87312c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
874352f7f91STakashi Iwai 	if (!knew)
875a35bd1e3STakashi Iwai 		return NULL;
876352f7f91STakashi Iwai 	knew->index = cidx;
877352f7f91STakashi Iwai 	if (get_amp_nid_(val))
878352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
879352f7f91STakashi Iwai 	knew->private_value = val;
880a35bd1e3STakashi Iwai 	return knew;
881352f7f91STakashi Iwai }
882352f7f91STakashi Iwai 
883352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
884352f7f91STakashi Iwai 				const char *pfx, const char *dir,
885352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
886352f7f91STakashi Iwai {
887975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
888352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
889a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
890a35bd1e3STakashi Iwai 		return -ENOMEM;
891a35bd1e3STakashi Iwai 	return 0;
892352f7f91STakashi Iwai }
893352f7f91STakashi Iwai 
894352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
895352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
896352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
897352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
898352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
899352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
900352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
901352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
902352f7f91STakashi Iwai 
903352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
904352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
905352f7f91STakashi Iwai {
906352f7f91STakashi Iwai 	unsigned int val;
907352f7f91STakashi Iwai 	if (!path)
908352f7f91STakashi Iwai 		return 0;
909352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
910352f7f91STakashi Iwai 	if (!val)
911352f7f91STakashi Iwai 		return 0;
912352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
913352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
914352f7f91STakashi Iwai }
915352f7f91STakashi Iwai 
916352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
917352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
918352f7f91STakashi Iwai 			       int type)
919352f7f91STakashi Iwai {
920352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
921352f7f91STakashi Iwai 	if (path) {
922352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
923352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
924352f7f91STakashi Iwai 			chs = 3; /* stereo */
925352f7f91STakashi Iwai 	}
926352f7f91STakashi Iwai 	return chs;
927352f7f91STakashi Iwai }
928352f7f91STakashi Iwai 
929352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
930352f7f91STakashi Iwai 			  struct nid_path *path)
931352f7f91STakashi Iwai {
932352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
933352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
934352f7f91STakashi Iwai }
935352f7f91STakashi Iwai 
936352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
937352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
938352f7f91STakashi Iwai  */
939352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
940352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
941352f7f91STakashi Iwai {
942352f7f91STakashi Iwai 	unsigned int val;
943352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
944352f7f91STakashi Iwai 
945352f7f91STakashi Iwai 	if (!path)
946352f7f91STakashi Iwai 		return 0;
947352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
948352f7f91STakashi Iwai 	if (!val)
949352f7f91STakashi Iwai 		return 0;
950352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
951352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
952352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
953352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
954352f7f91STakashi Iwai 		if (nums > 1) {
955352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
956352f7f91STakashi Iwai 			val |= nums << 19;
957352f7f91STakashi Iwai 		}
958352f7f91STakashi Iwai 	}
959352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
960352f7f91STakashi Iwai }
961352f7f91STakashi Iwai 
962352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
963352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
964352f7f91STakashi Iwai {
965352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
966352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
967352f7f91STakashi Iwai }
968352f7f91STakashi Iwai 
9697eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
970bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
9717eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
9727eebffd3STakashi Iwai {
9737eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9747eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
9757eebffd3STakashi Iwai 
9767eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
9777eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
9787eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
9797eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
9807eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
9817eebffd3STakashi Iwai 	}
982bc2eee29STakashi Iwai }
9837eebffd3STakashi Iwai 
984bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
985bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
986bc2eee29STakashi Iwai {
987bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
9887eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
9897eebffd3STakashi Iwai }
9907eebffd3STakashi Iwai 
991bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
992bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
993bc2eee29STakashi Iwai {
994bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
995bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
996bc2eee29STakashi Iwai }
997bc2eee29STakashi Iwai 
998247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
999247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1000247d85eeSTakashi Iwai {
1001247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1002247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1003247d85eeSTakashi Iwai }
1004247d85eeSTakashi Iwai 
1005352f7f91STakashi Iwai static const char * const channel_name[4] = {
1006352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1007352f7f91STakashi Iwai };
1008352f7f91STakashi Iwai 
1009352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1010247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1011247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1012352f7f91STakashi Iwai {
1013247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1014352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1015352f7f91STakashi Iwai 
1016352f7f91STakashi Iwai 	*index = 0;
1017352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1018247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1019352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1020352f7f91STakashi Iwai 
1021352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1022352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1023352f7f91STakashi Iwai 	 */
1024352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1025352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1026352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1027352f7f91STakashi Iwai 
1028247d85eeSTakashi Iwai 	/* multi-io channels */
1029247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1030247d85eeSTakashi Iwai 		return channel_name[ch];
1031247d85eeSTakashi Iwai 
1032352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1033352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1034247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1035247d85eeSTakashi Iwai 		 * don't name it as Speaker
1036247d85eeSTakashi Iwai 		 */
1037247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1038247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1039247d85eeSTakashi Iwai 			break;
1040352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1041352f7f91STakashi Iwai 			return "Speaker";
1042352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1043352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1044352f7f91STakashi Iwai 		break;
1045352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1046247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1047247d85eeSTakashi Iwai 		 * don't name it as Headphone
1048247d85eeSTakashi Iwai 		 */
1049247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1050247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1051247d85eeSTakashi Iwai 			break;
1052352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1053352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1054352f7f91STakashi Iwai 			break;
1055352f7f91STakashi Iwai 		*index = ch;
1056352f7f91STakashi Iwai 		return "Headphone";
1057247d85eeSTakashi Iwai 	}
1058247d85eeSTakashi Iwai 
1059247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1060352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
1061352f7f91STakashi Iwai 		return "PCM";
1062247d85eeSTakashi Iwai 
1063352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1064352f7f91STakashi Iwai 		snd_BUG();
1065352f7f91STakashi Iwai 		return "PCM";
1066352f7f91STakashi Iwai 	}
1067352f7f91STakashi Iwai 
1068352f7f91STakashi Iwai 	return channel_name[ch];
1069352f7f91STakashi Iwai }
1070352f7f91STakashi Iwai 
1071352f7f91STakashi Iwai /*
1072352f7f91STakashi Iwai  * Parse output paths
1073352f7f91STakashi Iwai  */
1074352f7f91STakashi Iwai 
1075352f7f91STakashi Iwai /* badness definition */
1076352f7f91STakashi Iwai enum {
1077352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1078352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1079352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1080352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1081352f7f91STakashi Iwai 	/* No possible multi-ios */
10821d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1083352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1084352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1085352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1086352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1087352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1088352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
108955a63d4dSTakashi Iwai 	/* No independent HP possible */
1090bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1091352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1092352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1093352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1094352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1095352f7f91STakashi Iwai 	/* Volume widget is shared */
1096352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1097352f7f91STakashi Iwai };
1098352f7f91STakashi Iwai 
10990e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1100352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1101352f7f91STakashi Iwai  *
1102352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1103352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1104352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1105352f7f91STakashi Iwai  */
11060e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1107352f7f91STakashi Iwai {
1108352f7f91STakashi Iwai 	hda_nid_t nid;
1109352f7f91STakashi Iwai 	unsigned int val;
1110352f7f91STakashi Iwai 	int badness = 0;
1111352f7f91STakashi Iwai 
1112352f7f91STakashi Iwai 	if (!path)
1113352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
11140e614dd0STakashi Iwai 
11150e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
11160e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
11170e614dd0STakashi Iwai 		return 0; /* already evaluated */
11180e614dd0STakashi Iwai 
1119352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1120352f7f91STakashi Iwai 	if (nid) {
1121352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1122352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1123352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1124352f7f91STakashi Iwai 		else
1125352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1126352f7f91STakashi Iwai 	} else
1127352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1128352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1129352f7f91STakashi Iwai 	if (nid) {
1130352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1131352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1132352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1133352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1134352f7f91STakashi Iwai 		else
1135352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1136352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1137352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1138352f7f91STakashi Iwai 		else
1139352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1140352f7f91STakashi Iwai 	} else
1141352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1142352f7f91STakashi Iwai 	return badness;
1143352f7f91STakashi Iwai }
1144352f7f91STakashi Iwai 
114598bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1146352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1147352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1148352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1149352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1150352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1151352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1152352f7f91STakashi Iwai };
11532698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1154352f7f91STakashi Iwai 
115598bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1156352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1157352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1158352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1159352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1160352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1161352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1162352f7f91STakashi Iwai };
11632698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1164352f7f91STakashi Iwai 
11657385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
11667385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
11677385df61STakashi Iwai {
11687385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
11697385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
11707385df61STakashi Iwai 
11717385df61STakashi Iwai 	if (cfg->line_outs > idx)
11727385df61STakashi Iwai 		return spec->private_dac_nids[idx];
11737385df61STakashi Iwai 	idx -= cfg->line_outs;
11747385df61STakashi Iwai 	if (spec->multi_ios > idx)
11757385df61STakashi Iwai 		return spec->multi_io[idx].dac;
11767385df61STakashi Iwai 	return 0;
11777385df61STakashi Iwai }
11787385df61STakashi Iwai 
11797385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
11807385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
11817385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
11827385df61STakashi Iwai {
11837385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
11847385df61STakashi Iwai }
11857385df61STakashi Iwai 
1186352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1187352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1188352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1189196c1766STakashi Iwai 			   int *path_idx,
1190352f7f91STakashi Iwai 			   const struct badness_table *bad)
1191352f7f91STakashi Iwai {
1192352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1193352f7f91STakashi Iwai 	int i, j;
1194352f7f91STakashi Iwai 	int badness = 0;
1195352f7f91STakashi Iwai 	hda_nid_t dac;
1196352f7f91STakashi Iwai 
1197352f7f91STakashi Iwai 	if (!num_outs)
1198352f7f91STakashi Iwai 		return 0;
1199352f7f91STakashi Iwai 
1200352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
12010c8c0f56STakashi Iwai 		struct nid_path *path;
1202352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
12031e0b5286STakashi Iwai 
12040e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
12050e614dd0STakashi Iwai 		if (path) {
12060e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
12071e0b5286STakashi Iwai 			continue;
12081e0b5286STakashi Iwai 		}
12091e0b5286STakashi Iwai 
12103690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
12113690739bSTakashi Iwai 		if (dacs[i]) {
12123690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
12133690739bSTakashi Iwai 				badness += bad->shared_primary;
12143690739bSTakashi Iwai 		}
12153690739bSTakashi Iwai 
12163690739bSTakashi Iwai 		if (!dacs[i])
1217352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1218352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1219980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1220352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1221352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1222352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1223352f7f91STakashi Iwai 					dacs[j] = 0;
1224980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1225196c1766STakashi Iwai 					path_idx[j] = 0;
1226352f7f91STakashi Iwai 					break;
1227352f7f91STakashi Iwai 				}
1228352f7f91STakashi Iwai 			}
1229352f7f91STakashi Iwai 		}
1230352f7f91STakashi Iwai 		dac = dacs[i];
1231352f7f91STakashi Iwai 		if (!dac) {
12327385df61STakashi Iwai 			if (num_outs > 2)
12337385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
12347385df61STakashi Iwai 			if (!dac)
12357385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
12367385df61STakashi Iwai 			if (!dac)
12377385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1238352f7f91STakashi Iwai 			if (dac) {
1239352f7f91STakashi Iwai 				if (!i)
1240352f7f91STakashi Iwai 					badness += bad->shared_primary;
1241352f7f91STakashi Iwai 				else if (i == 1)
1242352f7f91STakashi Iwai 					badness += bad->shared_surr;
1243352f7f91STakashi Iwai 				else
1244352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1245352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1246352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1247352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1248352f7f91STakashi Iwai 			} else if (!i)
1249352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1250352f7f91STakashi Iwai 			else
1251352f7f91STakashi Iwai 				badness += bad->no_dac;
1252352f7f91STakashi Iwai 		}
12531fa335b0STakashi Iwai 		if (!dac)
12541fa335b0STakashi Iwai 			continue;
12553ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1256117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1257b3a8c745STakashi Iwai 			/* try with aamix */
12583ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1259b3a8c745STakashi Iwai 		}
12601fa335b0STakashi Iwai 		if (!path) {
1261352f7f91STakashi Iwai 			dac = dacs[i] = 0;
12621fa335b0STakashi Iwai 			badness += bad->no_dac;
12631fa335b0STakashi Iwai 		} else {
1264a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1265e1284af7STakashi Iwai 			path->active = true;
1266196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
12670e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1268e1284af7STakashi Iwai 		}
1269352f7f91STakashi Iwai 	}
1270352f7f91STakashi Iwai 
1271352f7f91STakashi Iwai 	return badness;
1272352f7f91STakashi Iwai }
1273352f7f91STakashi Iwai 
1274352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1275352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1276352f7f91STakashi Iwai {
1277352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1278352f7f91STakashi Iwai 	int i;
1279352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1280352f7f91STakashi Iwai 
1281352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1282352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1283352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1284352f7f91STakashi Iwai 			continue;
1285352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1286352f7f91STakashi Iwai 			if (nid_found)
1287352f7f91STakashi Iwai 				return 0;
1288352f7f91STakashi Iwai 			nid_found = nid;
1289352f7f91STakashi Iwai 		}
1290352f7f91STakashi Iwai 	}
1291352f7f91STakashi Iwai 	return nid_found;
1292352f7f91STakashi Iwai }
1293352f7f91STakashi Iwai 
1294352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1295352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1296352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1297352f7f91STakashi Iwai {
1298352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1299352f7f91STakashi Iwai 
1300352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1301352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1302352f7f91STakashi Iwai 		return false;
1303352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1304352f7f91STakashi Iwai 		return false;
1305352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1306352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1307352f7f91STakashi Iwai 		return false;
1308352f7f91STakashi Iwai 	return true;
1309352f7f91STakashi Iwai }
1310352f7f91STakashi Iwai 
1311e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1312e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1313e22aab7dSTakashi Iwai {
1314e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1315e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1316e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1317e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1318e22aab7dSTakashi Iwai 	int type, i;
1319e22aab7dSTakashi Iwai 	int num_pins = 0;
1320e22aab7dSTakashi Iwai 
1321e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1322e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1323e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1324e22aab7dSTakashi Iwai 				continue;
1325e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1326e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1327e22aab7dSTakashi Iwai 				num_pins++;
1328e22aab7dSTakashi Iwai 		}
1329e22aab7dSTakashi Iwai 	}
1330e22aab7dSTakashi Iwai 	return num_pins;
1331e22aab7dSTakashi Iwai }
1332e22aab7dSTakashi Iwai 
1333352f7f91STakashi Iwai /*
1334352f7f91STakashi Iwai  * multi-io helper
1335352f7f91STakashi Iwai  *
1336352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1337352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1338352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1339352f7f91STakashi Iwai  * the badness value.
1340352f7f91STakashi Iwai  */
1341352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1342352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1343e22aab7dSTakashi Iwai 			  bool hardwired)
1344352f7f91STakashi Iwai {
1345352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1346352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1347e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1348352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1349352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1350352f7f91STakashi Iwai 	int badness = 0;
13510e614dd0STakashi Iwai 	struct nid_path *path;
1352352f7f91STakashi Iwai 
1353352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1354352f7f91STakashi Iwai 	if (old_pins >= 2)
1355352f7f91STakashi Iwai 		goto end_fill;
1356352f7f91STakashi Iwai 
1357e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1358352f7f91STakashi Iwai 	if (num_pins < 2)
1359352f7f91STakashi Iwai 		goto end_fill;
1360352f7f91STakashi Iwai 
1361352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1362352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1363352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1364352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1365352f7f91STakashi Iwai 
1366352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1367352f7f91STakashi Iwai 				continue;
1368352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1369352f7f91STakashi Iwai 				continue;
1370352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1371352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1372352f7f91STakashi Iwai 					break;
1373352f7f91STakashi Iwai 			}
1374352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1375352f7f91STakashi Iwai 				continue;
1376352f7f91STakashi Iwai 
1377352f7f91STakashi Iwai 			if (hardwired)
1378352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1379352f7f91STakashi Iwai 			else if (!dac)
1380352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1381352f7f91STakashi Iwai 			if (!dac) {
1382352f7f91STakashi Iwai 				badness++;
1383352f7f91STakashi Iwai 				continue;
1384352f7f91STakashi Iwai 			}
13853ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
13863ca529d3STakashi Iwai 						    -spec->mixer_nid);
13870c8c0f56STakashi Iwai 			if (!path) {
1388352f7f91STakashi Iwai 				badness++;
1389352f7f91STakashi Iwai 				continue;
1390352f7f91STakashi Iwai 			}
1391a769409cSTakashi Iwai 			/* print_nid_path("multiio", path); */
1392352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1393352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1394196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1395196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1396352f7f91STakashi Iwai 			spec->multi_ios++;
1397352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1398352f7f91STakashi Iwai 				break;
1399352f7f91STakashi Iwai 		}
1400352f7f91STakashi Iwai 	}
1401352f7f91STakashi Iwai  end_fill:
1402352f7f91STakashi Iwai 	if (badness)
1403352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1404352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1405352f7f91STakashi Iwai 		if (hardwired)
1406352f7f91STakashi Iwai 			return 1; /* nothing found */
1407352f7f91STakashi Iwai 		else
1408352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1409352f7f91STakashi Iwai 	}
1410352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1411352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1412352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1413352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1414352f7f91STakashi Iwai 		return badness;
1415352f7f91STakashi Iwai 	}
1416352f7f91STakashi Iwai 
1417352f7f91STakashi Iwai 	/* assign volume and mute controls */
14180e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
14190e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
14200e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
14210e614dd0STakashi Iwai 	}
1422352f7f91STakashi Iwai 
1423352f7f91STakashi Iwai 	return badness;
1424352f7f91STakashi Iwai }
1425352f7f91STakashi Iwai 
1426352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1427352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1428196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1429352f7f91STakashi Iwai {
1430b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1431352f7f91STakashi Iwai 	int i;
1432352f7f91STakashi Iwai 	bool found = false;
1433352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
14340c8c0f56STakashi Iwai 		struct nid_path *path;
1435352f7f91STakashi Iwai 		hda_nid_t dac;
1436352f7f91STakashi Iwai 		if (dacs[i])
1437352f7f91STakashi Iwai 			continue;
1438352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1439352f7f91STakashi Iwai 		if (!dac)
1440352f7f91STakashi Iwai 			continue;
14413ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
14423ca529d3STakashi Iwai 					    -spec->mixer_nid);
1443117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
14443ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
14450c8c0f56STakashi Iwai 		if (path) {
1446352f7f91STakashi Iwai 			dacs[i] = dac;
1447352f7f91STakashi Iwai 			found = true;
1448a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1449e1284af7STakashi Iwai 			path->active = true;
1450196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1451352f7f91STakashi Iwai 		}
1452352f7f91STakashi Iwai 	}
1453352f7f91STakashi Iwai 	return found;
1454352f7f91STakashi Iwai }
1455352f7f91STakashi Iwai 
1456c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1457c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1458c30aa7b2STakashi Iwai {
14593ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1460c30aa7b2STakashi Iwai 	struct nid_path *path;
14615ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1462c30aa7b2STakashi Iwai 
1463c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
14643ca529d3STakashi Iwai 	if (!path || !path->depth ||
14653ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1466c30aa7b2STakashi Iwai 		return 0;
14675ead56f2STakashi Iwai 	path_dac = path->path[0];
14685ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1469f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1470f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1471f87498b6STakashi Iwai 	if (!path) {
14725ead56f2STakashi Iwai 		if (dac != path_dac)
14735ead56f2STakashi Iwai 			dac = path_dac;
1474f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1475f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1476f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1477f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
14785ead56f2STakashi Iwai 		else
14795ead56f2STakashi Iwai 			dac = 0;
1480f87498b6STakashi Iwai 		if (dac)
1481f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
14823ca529d3STakashi Iwai 						    spec->mixer_nid);
1483f87498b6STakashi Iwai 	}
1484c30aa7b2STakashi Iwai 	if (!path)
1485c30aa7b2STakashi Iwai 		return 0;
1486a769409cSTakashi Iwai 	/* print_nid_path("output-aamix", path); */
1487c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1488c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1489c30aa7b2STakashi Iwai }
1490c30aa7b2STakashi Iwai 
149155a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
149255a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
149355a63d4dSTakashi Iwai {
149455a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
149555a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
149655a63d4dSTakashi Iwai 	struct nid_path *path;
149755a63d4dSTakashi Iwai 	int i, idx;
149855a63d4dSTakashi Iwai 
149955a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
150055a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
150155a63d4dSTakashi Iwai 	else
150255a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
150355a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
150455a63d4dSTakashi Iwai 	if (!path)
150555a63d4dSTakashi Iwai 		return false;
150655a63d4dSTakashi Iwai 
150755a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
150855a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
150955a63d4dSTakashi Iwai 		return true;
151055a63d4dSTakashi Iwai 
151155a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
151255a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
151355a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
151455a63d4dSTakashi Iwai 			break;
151555a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
151655a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
151755a63d4dSTakashi Iwai 			return false;
151855a63d4dSTakashi Iwai 	}
151955a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
152055a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
152155a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
152255a63d4dSTakashi Iwai 			return false;
152355a63d4dSTakashi Iwai 	}
152455a63d4dSTakashi Iwai 
152555a63d4dSTakashi Iwai 	return true;
152655a63d4dSTakashi Iwai }
152755a63d4dSTakashi Iwai 
1528a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1529a07a949bSTakashi Iwai  * shared dac pointed by the paths
1530a07a949bSTakashi Iwai  */
1531a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1532a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1533a07a949bSTakashi Iwai {
1534a07a949bSTakashi Iwai 	struct nid_path *path;
1535a07a949bSTakashi Iwai 	int i;
1536a07a949bSTakashi Iwai 
1537a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1538a07a949bSTakashi Iwai 		if (dacs[i])
1539a07a949bSTakashi Iwai 			continue;
1540a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1541a07a949bSTakashi Iwai 		if (!path)
1542a07a949bSTakashi Iwai 			continue;
1543a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1544a07a949bSTakashi Iwai 	}
1545a07a949bSTakashi Iwai }
1546a07a949bSTakashi Iwai 
1547352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1548352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1549352f7f91STakashi Iwai 			      bool fill_hardwired,
1550352f7f91STakashi Iwai 			      bool fill_mio_first)
1551352f7f91STakashi Iwai {
1552352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1553352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1554352f7f91STakashi Iwai 	int i, err, badness;
1555352f7f91STakashi Iwai 
1556352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1557352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1558352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1559352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1560352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1561352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1562352f7f91STakashi Iwai 	spec->multi_ios = 0;
1563352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1564cd5be3f9STakashi Iwai 
1565cd5be3f9STakashi Iwai 	/* clear path indices */
1566cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1567cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1568cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1569cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1570cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1571c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1572cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1573cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1574cd5be3f9STakashi Iwai 
1575352f7f91STakashi Iwai 	badness = 0;
1576352f7f91STakashi Iwai 
1577352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1578352f7f91STakashi Iwai 	if (fill_hardwired) {
1579352f7f91STakashi Iwai 		bool mapped;
1580352f7f91STakashi Iwai 		do {
1581352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1582352f7f91STakashi Iwai 					     cfg->line_out_pins,
1583196c1766STakashi Iwai 					     spec->private_dac_nids,
1584196c1766STakashi Iwai 					     spec->out_paths);
1585352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1586352f7f91STakashi Iwai 					      cfg->hp_pins,
1587196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1588196c1766STakashi Iwai 					      spec->hp_paths);
1589352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1590352f7f91STakashi Iwai 					      cfg->speaker_pins,
1591196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1592196c1766STakashi Iwai 					      spec->speaker_paths);
1593da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1594da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1595352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1596e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1597352f7f91STakashi Iwai 				if (!err)
1598352f7f91STakashi Iwai 					mapped = true;
1599352f7f91STakashi Iwai 			}
1600352f7f91STakashi Iwai 		} while (mapped);
1601352f7f91STakashi Iwai 	}
1602352f7f91STakashi Iwai 
1603352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1604196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
160598bd1115STakashi Iwai 				   spec->main_out_badness);
1606352f7f91STakashi Iwai 
1607da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1608352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1609352f7f91STakashi Iwai 		/* try to fill multi-io first */
1610e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1611352f7f91STakashi Iwai 		if (err < 0)
1612352f7f91STakashi Iwai 			return err;
1613352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1614352f7f91STakashi Iwai 	}
1615352f7f91STakashi Iwai 
1616352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1617352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1618352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1619196c1766STakashi Iwai 				      spec->hp_paths,
162098bd1115STakashi Iwai 				      spec->extra_out_badness);
1621352f7f91STakashi Iwai 		if (err < 0)
1622352f7f91STakashi Iwai 			return err;
1623352f7f91STakashi Iwai 		badness += err;
1624352f7f91STakashi Iwai 	}
1625352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1626352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1627352f7f91STakashi Iwai 				      cfg->speaker_pins,
1628352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1629196c1766STakashi Iwai 				      spec->speaker_paths,
163098bd1115STakashi Iwai 				      spec->extra_out_badness);
1631352f7f91STakashi Iwai 		if (err < 0)
1632352f7f91STakashi Iwai 			return err;
1633352f7f91STakashi Iwai 		badness += err;
1634352f7f91STakashi Iwai 	}
1635da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1636da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1637e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1638352f7f91STakashi Iwai 		if (err < 0)
1639352f7f91STakashi Iwai 			return err;
1640352f7f91STakashi Iwai 		badness += err;
1641352f7f91STakashi Iwai 	}
1642e22aab7dSTakashi Iwai 
1643c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1644c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1645c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1646c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1647c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1648c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1649c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1650c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1651c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1652c30aa7b2STakashi Iwai 	}
1653c30aa7b2STakashi Iwai 
1654da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1655da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1656e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1657e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1658352f7f91STakashi Iwai 
1659a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1660a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1661a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1662a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1663a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1664a07a949bSTakashi Iwai 		else {
1665a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1666a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1667a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1668a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1669a07a949bSTakashi Iwai 		}
1670a07a949bSTakashi Iwai 	}
1671a07a949bSTakashi Iwai 
1672a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1673c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1674a07a949bSTakashi Iwai 
1675352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1676352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1677352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1678352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1679352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1680352f7f91STakashi Iwai 		spec->multi_ios = 0;
1681352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1682352f7f91STakashi Iwai 	}
1683352f7f91STakashi Iwai 
168455a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
168555a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
168655a63d4dSTakashi Iwai 
1687a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1688a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1689a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1690a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1691a07a949bSTakashi Iwai 				   spec->hp_paths);
1692a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1693a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1694a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1695a07a949bSTakashi Iwai 				   spec->speaker_paths);
1696a07a949bSTakashi Iwai 
1697352f7f91STakashi Iwai 	return badness;
1698352f7f91STakashi Iwai }
1699352f7f91STakashi Iwai 
1700352f7f91STakashi Iwai #define DEBUG_BADNESS
1701352f7f91STakashi Iwai 
1702352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1703352f7f91STakashi Iwai #define debug_badness	snd_printdd
1704352f7f91STakashi Iwai #else
1705352f7f91STakashi Iwai #define debug_badness(...)
1706352f7f91STakashi Iwai #endif
1707352f7f91STakashi Iwai 
1708a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1709a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1710a769409cSTakashi Iwai 				      const char *pfx, int idx)
1711352f7f91STakashi Iwai {
1712a769409cSTakashi Iwai 	struct nid_path *path;
1713a769409cSTakashi Iwai 
1714a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1715a769409cSTakashi Iwai 	if (path)
1716a769409cSTakashi Iwai 		print_nid_path(pfx, path);
1717a769409cSTakashi Iwai }
1718a769409cSTakashi Iwai 
1719a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1720a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1721a769409cSTakashi Iwai {
1722a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1723a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1724a769409cSTakashi Iwai 	int i;
1725a769409cSTakashi Iwai 
1726a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1727352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1728708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1729352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1730352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1731352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1732a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1733a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1734a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1735a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1736352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1737352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1738352f7f91STakashi Iwai 			      spec->multi_ios,
1739352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1740352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1741a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1742a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1743a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1744a769409cSTakashi Iwai 	if (cfg->hp_outs)
1745352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1746352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1747708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1748352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1749352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1750352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1751352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1752a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1753a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1754a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1755352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1756352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1757352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1758352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1759352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1760352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1761352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1762a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1763a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1764a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1765a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1766352f7f91STakashi Iwai }
1767a769409cSTakashi Iwai #else
1768a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1769a769409cSTakashi Iwai #endif
1770352f7f91STakashi Iwai 
1771352f7f91STakashi Iwai /* find all available DACs of the codec */
1772352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1773352f7f91STakashi Iwai {
1774352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1775352f7f91STakashi Iwai 	int i;
1776352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1777352f7f91STakashi Iwai 
1778352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1779352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1780352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1781352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1782352f7f91STakashi Iwai 			continue;
1783352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1784352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1785352f7f91STakashi Iwai 			break;
1786352f7f91STakashi Iwai 		}
1787352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1788352f7f91STakashi Iwai 	}
1789352f7f91STakashi Iwai }
1790352f7f91STakashi Iwai 
1791352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1792352f7f91STakashi Iwai {
1793352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1794352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1795352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
17969314a581STakashi Iwai 	unsigned int val;
1797352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1798352f7f91STakashi Iwai 	int badness;
1799352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1800352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1801352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1802352f7f91STakashi Iwai 
1803352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1804352f7f91STakashi Iwai 	if (!best_cfg)
1805352f7f91STakashi Iwai 		return -ENOMEM;
1806352f7f91STakashi Iwai 	*best_cfg = *cfg;
1807352f7f91STakashi Iwai 
1808352f7f91STakashi Iwai 	for (;;) {
1809352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1810352f7f91STakashi Iwai 					     fill_mio_first);
1811352f7f91STakashi Iwai 		if (badness < 0) {
1812352f7f91STakashi Iwai 			kfree(best_cfg);
1813352f7f91STakashi Iwai 			return badness;
1814352f7f91STakashi Iwai 		}
1815352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1816352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1817352f7f91STakashi Iwai 			      badness);
1818a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1819352f7f91STakashi Iwai 		if (badness < best_badness) {
1820352f7f91STakashi Iwai 			best_badness = badness;
1821352f7f91STakashi Iwai 			*best_cfg = *cfg;
1822352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1823352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1824352f7f91STakashi Iwai 		}
1825352f7f91STakashi Iwai 		if (!badness)
1826352f7f91STakashi Iwai 			break;
1827352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1828352f7f91STakashi Iwai 		if (!fill_mio_first)
1829352f7f91STakashi Iwai 			continue;
1830352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1831352f7f91STakashi Iwai 		if (!fill_hardwired)
1832352f7f91STakashi Iwai 			continue;
1833352f7f91STakashi Iwai 		if (hp_spk_swapped)
1834352f7f91STakashi Iwai 			break;
1835352f7f91STakashi Iwai 		hp_spk_swapped = true;
1836352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1837352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1838352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1839352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1840352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1841352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1842352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1843352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1844352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1845352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1846352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1847352f7f91STakashi Iwai 			fill_hardwired = true;
1848352f7f91STakashi Iwai 			continue;
1849352f7f91STakashi Iwai 		}
1850352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1851352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1852352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1853352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1854352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1855352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1856352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1857352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1858352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1859352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1860352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1861352f7f91STakashi Iwai 			fill_hardwired = true;
1862352f7f91STakashi Iwai 			continue;
1863352f7f91STakashi Iwai 		}
1864352f7f91STakashi Iwai 		break;
1865352f7f91STakashi Iwai 	}
1866352f7f91STakashi Iwai 
1867352f7f91STakashi Iwai 	if (badness) {
18680c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1869352f7f91STakashi Iwai 		*cfg = *best_cfg;
1870352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1871352f7f91STakashi Iwai 	}
1872352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1873352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1874a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
1875352f7f91STakashi Iwai 
1876352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1877352f7f91STakashi Iwai 		struct nid_path *path;
1878196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1879352f7f91STakashi Iwai 		if (path)
1880352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
18817a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
18827a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
18837a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1884352f7f91STakashi Iwai 	}
1885352f7f91STakashi Iwai 
18869314a581STakashi Iwai 	/* set initial pinctl targets */
18879314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
18889314a581STakashi Iwai 		val = PIN_HP;
18899314a581STakashi Iwai 	else
18909314a581STakashi Iwai 		val = PIN_OUT;
18919314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
18929314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
18939314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
18949314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
18959314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
18969314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
18979314a581STakashi Iwai 				cfg->speaker_pins, val);
18989314a581STakashi Iwai 	}
18999314a581STakashi Iwai 
190055a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
190155a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
190255a63d4dSTakashi Iwai 		spec->indep_hp = 0;
190355a63d4dSTakashi Iwai 
1904352f7f91STakashi Iwai 	kfree(best_cfg);
1905352f7f91STakashi Iwai 	return 0;
1906352f7f91STakashi Iwai }
1907352f7f91STakashi Iwai 
1908352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1909352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1910352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1911352f7f91STakashi Iwai {
1912352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1913352f7f91STakashi Iwai 	int i, err, noutputs;
1914352f7f91STakashi Iwai 
1915352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1916352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1917352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1918352f7f91STakashi Iwai 
1919352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1920352f7f91STakashi Iwai 		const char *name;
1921352f7f91STakashi Iwai 		int index;
1922352f7f91STakashi Iwai 		struct nid_path *path;
1923352f7f91STakashi Iwai 
1924196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1925352f7f91STakashi Iwai 		if (!path)
1926352f7f91STakashi Iwai 			continue;
1927247d85eeSTakashi Iwai 
1928247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1929352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1930352f7f91STakashi Iwai 			/* Center/LFE */
1931352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1932352f7f91STakashi Iwai 			if (err < 0)
1933352f7f91STakashi Iwai 				return err;
1934352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1935352f7f91STakashi Iwai 			if (err < 0)
1936352f7f91STakashi Iwai 				return err;
1937247d85eeSTakashi Iwai 		} else {
1938247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1939247d85eeSTakashi Iwai 			if (err < 0)
1940247d85eeSTakashi Iwai 				return err;
1941247d85eeSTakashi Iwai 		}
1942247d85eeSTakashi Iwai 
1943247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1944247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1945352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1946352f7f91STakashi Iwai 			if (err < 0)
1947352f7f91STakashi Iwai 				return err;
1948352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1949352f7f91STakashi Iwai 			if (err < 0)
1950352f7f91STakashi Iwai 				return err;
1951352f7f91STakashi Iwai 		} else {
1952352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1953352f7f91STakashi Iwai 			if (err < 0)
1954352f7f91STakashi Iwai 				return err;
1955352f7f91STakashi Iwai 		}
1956352f7f91STakashi Iwai 	}
1957352f7f91STakashi Iwai 	return 0;
1958352f7f91STakashi Iwai }
1959352f7f91STakashi Iwai 
1960c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1961196c1766STakashi Iwai 			    const char *pfx, int cidx)
1962352f7f91STakashi Iwai {
1963352f7f91STakashi Iwai 	struct nid_path *path;
1964352f7f91STakashi Iwai 	int err;
1965352f7f91STakashi Iwai 
1966196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1967352f7f91STakashi Iwai 	if (!path)
1968352f7f91STakashi Iwai 		return 0;
1969352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1970352f7f91STakashi Iwai 	if (err < 0)
1971352f7f91STakashi Iwai 		return err;
1972352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1973352f7f91STakashi Iwai 	if (err < 0)
1974352f7f91STakashi Iwai 		return err;
1975352f7f91STakashi Iwai 	return 0;
1976352f7f91STakashi Iwai }
1977352f7f91STakashi Iwai 
1978352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1979352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1980196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1981352f7f91STakashi Iwai {
1982c2c80383STakashi Iwai 	int i;
1983352f7f91STakashi Iwai 
1984352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1985c2c80383STakashi Iwai 		const char *name;
1986975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1987c2c80383STakashi Iwai 		int err, idx = 0;
1988c2c80383STakashi Iwai 
1989c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1990c2c80383STakashi Iwai 			name = "Bass Speaker";
1991c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1992c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1993352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1994c2c80383STakashi Iwai 			name = tmp;
1995352f7f91STakashi Iwai 		} else {
1996c2c80383STakashi Iwai 			name = pfx;
1997c2c80383STakashi Iwai 			idx = i;
1998352f7f91STakashi Iwai 		}
1999c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2000352f7f91STakashi Iwai 		if (err < 0)
2001352f7f91STakashi Iwai 			return err;
2002352f7f91STakashi Iwai 	}
2003352f7f91STakashi Iwai 	return 0;
2004352f7f91STakashi Iwai }
2005352f7f91STakashi Iwai 
2006352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2007352f7f91STakashi Iwai {
2008352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2009352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2010196c1766STakashi Iwai 				 spec->hp_paths,
2011352f7f91STakashi Iwai 				 "Headphone");
2012352f7f91STakashi Iwai }
2013352f7f91STakashi Iwai 
2014352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2015352f7f91STakashi Iwai {
2016352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2017352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2018196c1766STakashi Iwai 				 spec->speaker_paths,
2019352f7f91STakashi Iwai 				 "Speaker");
2020352f7f91STakashi Iwai }
2021352f7f91STakashi Iwai 
2022352f7f91STakashi Iwai /*
202338cf6f1aSTakashi Iwai  * independent HP controls
202438cf6f1aSTakashi Iwai  */
202538cf6f1aSTakashi Iwai 
2026963afde9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
202738cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
202838cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
202938cf6f1aSTakashi Iwai {
203038cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
203138cf6f1aSTakashi Iwai }
203238cf6f1aSTakashi Iwai 
203338cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
203438cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
203538cf6f1aSTakashi Iwai {
203638cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
203738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
203838cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
203938cf6f1aSTakashi Iwai 	return 0;
204038cf6f1aSTakashi Iwai }
204138cf6f1aSTakashi Iwai 
2042a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2043a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2044a1e908edSTakashi Iwai 			       int out_type);
2045a1e908edSTakashi Iwai 
204638cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
204738cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
204838cf6f1aSTakashi Iwai {
204938cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
205038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
205138cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
205238cf6f1aSTakashi Iwai 	int ret = 0;
205338cf6f1aSTakashi Iwai 
205438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
205538cf6f1aSTakashi Iwai 	if (spec->active_streams) {
205638cf6f1aSTakashi Iwai 		ret = -EBUSY;
205738cf6f1aSTakashi Iwai 		goto unlock;
205838cf6f1aSTakashi Iwai 	}
205938cf6f1aSTakashi Iwai 
206038cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2061a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2062a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2063a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2064a1e908edSTakashi Iwai 		else
2065a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2066a1e908edSTakashi Iwai 
2067a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2068a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2069a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2070a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2071a1e908edSTakashi Iwai 						   spec->out_paths[0],
2072a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2073a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2074a1e908edSTakashi Iwai 			else
2075a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2076a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2077a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2078a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2079a1e908edSTakashi Iwai 		}
2080a1e908edSTakashi Iwai 
208138cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
208238cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2083a1e908edSTakashi Iwai 			*dacp = 0;
208438cf6f1aSTakashi Iwai 		else
2085a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
208692603c59STakashi Iwai 
2087963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
208838cf6f1aSTakashi Iwai 		ret = 1;
208938cf6f1aSTakashi Iwai 	}
209038cf6f1aSTakashi Iwai  unlock:
209138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
209238cf6f1aSTakashi Iwai 	return ret;
209338cf6f1aSTakashi Iwai }
209438cf6f1aSTakashi Iwai 
209538cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
209638cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
209738cf6f1aSTakashi Iwai 	.name = "Independent HP",
209838cf6f1aSTakashi Iwai 	.info = indep_hp_info,
209938cf6f1aSTakashi Iwai 	.get = indep_hp_get,
210038cf6f1aSTakashi Iwai 	.put = indep_hp_put,
210138cf6f1aSTakashi Iwai };
210238cf6f1aSTakashi Iwai 
210338cf6f1aSTakashi Iwai 
210438cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
210538cf6f1aSTakashi Iwai {
210638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2107a1e908edSTakashi Iwai 	hda_nid_t dac;
210838cf6f1aSTakashi Iwai 
210938cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
211038cf6f1aSTakashi Iwai 		return 0;
2111a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2112a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2113a1e908edSTakashi Iwai 	else
2114a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2115a1e908edSTakashi Iwai 	if (!dac) {
211638cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
211738cf6f1aSTakashi Iwai 		return 0;
211838cf6f1aSTakashi Iwai 	}
211938cf6f1aSTakashi Iwai 
212038cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2121a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
212238cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
212338cf6f1aSTakashi Iwai 		return -ENOMEM;
212438cf6f1aSTakashi Iwai 	return 0;
212538cf6f1aSTakashi Iwai }
212638cf6f1aSTakashi Iwai 
212738cf6f1aSTakashi Iwai /*
2128352f7f91STakashi Iwai  * channel mode enum control
2129352f7f91STakashi Iwai  */
2130352f7f91STakashi Iwai 
2131352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2132352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2133352f7f91STakashi Iwai {
2134352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2135352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2136a07a949bSTakashi Iwai 	int chs;
2137352f7f91STakashi Iwai 
2138352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2139352f7f91STakashi Iwai 	uinfo->count = 1;
2140352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2141352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2142352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2143a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2144a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2145352f7f91STakashi Iwai 	return 0;
2146352f7f91STakashi Iwai }
2147352f7f91STakashi Iwai 
2148352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2149352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2150352f7f91STakashi Iwai {
2151352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2152352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2153a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2154a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2155352f7f91STakashi Iwai 	return 0;
2156352f7f91STakashi Iwai }
2157352f7f91STakashi Iwai 
2158196c1766STakashi Iwai static inline struct nid_path *
2159196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2160196c1766STakashi Iwai {
2161196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2162196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2163196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2164196c1766STakashi Iwai }
2165196c1766STakashi Iwai 
2166a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2167a5cc2509STakashi Iwai 
216865033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
216965033cc8STakashi Iwai  * used for output paths
217065033cc8STakashi Iwai  */
217165033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
217265033cc8STakashi Iwai {
217365033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
217465033cc8STakashi Iwai }
217565033cc8STakashi Iwai 
2176352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2177352f7f91STakashi Iwai {
2178352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2179352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2180352f7f91STakashi Iwai 	struct nid_path *path;
2181352f7f91STakashi Iwai 
2182196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2183352f7f91STakashi Iwai 	if (!path)
2184352f7f91STakashi Iwai 		return -EINVAL;
2185352f7f91STakashi Iwai 
2186352f7f91STakashi Iwai 	if (path->active == output)
2187352f7f91STakashi Iwai 		return 0;
2188352f7f91STakashi Iwai 
2189352f7f91STakashi Iwai 	if (output) {
21902c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
219165033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2192d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2193352f7f91STakashi Iwai 	} else {
2194d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
219565033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
21962c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
219755196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2198352f7f91STakashi Iwai 	}
2199a365fed9STakashi Iwai 
2200a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2201a5cc2509STakashi Iwai 	update_automute_all(codec);
2202a365fed9STakashi Iwai 
2203352f7f91STakashi Iwai 	return 0;
2204352f7f91STakashi Iwai }
2205352f7f91STakashi Iwai 
2206352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2207352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2208352f7f91STakashi Iwai {
2209352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2210352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2211352f7f91STakashi Iwai 	int i, ch;
2212352f7f91STakashi Iwai 
2213352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2214352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2215352f7f91STakashi Iwai 		return -EINVAL;
2216a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2217352f7f91STakashi Iwai 		return 0;
2218a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2219352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2220352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2221352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2222352f7f91STakashi Iwai 					  spec->const_channel_count);
2223352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2224352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2225352f7f91STakashi Iwai 	return 1;
2226352f7f91STakashi Iwai }
2227352f7f91STakashi Iwai 
2228352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2229352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2230352f7f91STakashi Iwai 	.name = "Channel Mode",
2231352f7f91STakashi Iwai 	.info = ch_mode_info,
2232352f7f91STakashi Iwai 	.get = ch_mode_get,
2233352f7f91STakashi Iwai 	.put = ch_mode_put,
2234352f7f91STakashi Iwai };
2235352f7f91STakashi Iwai 
2236352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2237352f7f91STakashi Iwai {
2238352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2239352f7f91STakashi Iwai 
2240352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
224112c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2242352f7f91STakashi Iwai 			return -ENOMEM;
2243352f7f91STakashi Iwai 	}
2244352f7f91STakashi Iwai 	return 0;
2245352f7f91STakashi Iwai }
2246352f7f91STakashi Iwai 
2247352f7f91STakashi Iwai /*
2248c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2249c30aa7b2STakashi Iwai  */
2250c30aa7b2STakashi Iwai 
2251c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2252c30aa7b2STakashi Iwai 
2253c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2254c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2255c30aa7b2STakashi Iwai {
2256c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2257c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2258c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2259c30aa7b2STakashi Iwai 	return 0;
2260c30aa7b2STakashi Iwai }
2261c30aa7b2STakashi Iwai 
2262c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2263a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2264a1e908edSTakashi Iwai 			       int out_type)
2265c30aa7b2STakashi Iwai {
2266a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2267c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2268c30aa7b2STakashi Iwai 
2269c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2270c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2271c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2272c30aa7b2STakashi Iwai 		return;
2273a1e908edSTakashi Iwai 
2274a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2275a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2276a1e908edSTakashi Iwai 	 */
2277a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2278a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2279a1e908edSTakashi Iwai 		do_mix = false;
2280a1e908edSTakashi Iwai 
2281c30aa7b2STakashi Iwai 	if (do_mix) {
2282c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2283c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
228455196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2285c30aa7b2STakashi Iwai 	} else {
228665033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
228765033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
228855196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2289c30aa7b2STakashi Iwai 	}
2290c30aa7b2STakashi Iwai }
2291c30aa7b2STakashi Iwai 
2292c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2293c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2294c30aa7b2STakashi Iwai {
2295c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2296c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2297c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2298c30aa7b2STakashi Iwai 
2299c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2300c30aa7b2STakashi Iwai 		return 0;
2301c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2302c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2303a1e908edSTakashi Iwai 			   spec->aamix_out_paths[0],
2304a1e908edSTakashi Iwai 			   spec->autocfg.line_out_type);
2305c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2306a1e908edSTakashi Iwai 			   spec->aamix_out_paths[1],
2307a1e908edSTakashi Iwai 			   AUTO_PIN_HP_OUT);
2308c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2309a1e908edSTakashi Iwai 			   spec->aamix_out_paths[2],
2310a1e908edSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
2311c30aa7b2STakashi Iwai 	return 1;
2312c30aa7b2STakashi Iwai }
2313c30aa7b2STakashi Iwai 
2314c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2315c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2316c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2317c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2318c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2319c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2320c30aa7b2STakashi Iwai };
2321c30aa7b2STakashi Iwai 
2322c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2323c30aa7b2STakashi Iwai {
2324c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2325c30aa7b2STakashi Iwai 
2326c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2327c30aa7b2STakashi Iwai 		return 0;
2328c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2329c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2330c30aa7b2STakashi Iwai 		return 0;
2331c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2332c30aa7b2STakashi Iwai 		return -ENOMEM;
2333a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2334c30aa7b2STakashi Iwai 	return 0;
2335c30aa7b2STakashi Iwai }
2336c30aa7b2STakashi Iwai 
2337c30aa7b2STakashi Iwai /*
2338352f7f91STakashi Iwai  * shared headphone/mic handling
2339352f7f91STakashi Iwai  */
2340352f7f91STakashi Iwai 
2341352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2342352f7f91STakashi Iwai 
2343352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2344967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2345352f7f91STakashi Iwai {
2346352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2347967303daSTakashi Iwai 	bool as_mic;
2348352f7f91STakashi Iwai 	unsigned int val;
2349967303daSTakashi Iwai 	hda_nid_t pin;
2350967303daSTakashi Iwai 
2351967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2352967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2353967303daSTakashi Iwai 
2354967303daSTakashi Iwai 	if (!force) {
2355967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2356967303daSTakashi Iwai 		if (as_mic) {
2357967303daSTakashi Iwai 			if (val & PIN_IN)
2358967303daSTakashi Iwai 				return;
2359967303daSTakashi Iwai 		} else {
2360967303daSTakashi Iwai 			if (val & PIN_OUT)
2361967303daSTakashi Iwai 				return;
2362967303daSTakashi Iwai 		}
2363967303daSTakashi Iwai 	}
2364352f7f91STakashi Iwai 
2365352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2366967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2367967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2368967303daSTakashi Iwai 	 */
2369352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2370352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2371352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2372352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
23737594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2374967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2375352f7f91STakashi Iwai 	}
2376352f7f91STakashi Iwai 
23778ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2378967303daSTakashi Iwai 		if (as_mic)
2379967303daSTakashi Iwai 			val |= PIN_IN;
2380967303daSTakashi Iwai 		else
2381967303daSTakashi Iwai 			val = PIN_HP;
23822c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2383963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
23848ba955ceSTakashi Iwai 	}
2385352f7f91STakashi Iwai }
2386352f7f91STakashi Iwai 
2387352f7f91STakashi Iwai /* create a shared input with the headphone out */
2388967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2389352f7f91STakashi Iwai {
2390352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2391352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2392352f7f91STakashi Iwai 	unsigned int defcfg;
2393352f7f91STakashi Iwai 	hda_nid_t nid;
2394352f7f91STakashi Iwai 
2395967303daSTakashi Iwai 	if (!spec->hp_mic) {
2396967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2397352f7f91STakashi Iwai 			return 0;
2398967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2399967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2400967303daSTakashi Iwai 		 */
2401967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2402967303daSTakashi Iwai 			return 0;
2403967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2404352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2405352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2406352f7f91STakashi Iwai 				return 0;
2407967303daSTakashi Iwai 		}
2408967303daSTakashi Iwai 	}
2409352f7f91STakashi Iwai 
2410967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2411967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2412967303daSTakashi Iwai 		return 0;
2413967303daSTakashi Iwai 
2414967303daSTakashi Iwai 	nid = 0;
2415967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2416967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2417967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2418967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2419967303daSTakashi Iwai 	if (!nid)
2420967303daSTakashi Iwai 		return 0;
2421352f7f91STakashi Iwai 
2422352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2423352f7f91STakashi Iwai 		return 0; /* no input */
2424352f7f91STakashi Iwai 
2425967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2426967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2427cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2428967303daSTakashi Iwai 	cfg->num_inputs++;
2429967303daSTakashi Iwai 	spec->hp_mic = 1;
2430967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2431967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2432967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
2433352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2434352f7f91STakashi Iwai 	return 0;
2435352f7f91STakashi Iwai }
2436352f7f91STakashi Iwai 
2437978e77e7STakashi Iwai /*
2438978e77e7STakashi Iwai  * output jack mode
2439978e77e7STakashi Iwai  */
24405f171baaSTakashi Iwai 
24415f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
24425f171baaSTakashi Iwai 
24435f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
24445f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
24455f171baaSTakashi Iwai };
24465f171baaSTakashi Iwai 
2447978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2448978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2449978e77e7STakashi Iwai {
24505f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2451978e77e7STakashi Iwai }
2452978e77e7STakashi Iwai 
2453978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2454978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2455978e77e7STakashi Iwai {
2456978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2457978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2458978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2459978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2460978e77e7STakashi Iwai 	else
2461978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2462978e77e7STakashi Iwai 	return 0;
2463978e77e7STakashi Iwai }
2464978e77e7STakashi Iwai 
2465978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2466978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2467978e77e7STakashi Iwai {
2468978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2469978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2470978e77e7STakashi Iwai 	unsigned int val;
2471978e77e7STakashi Iwai 
2472978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2473978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2474978e77e7STakashi Iwai 		return 0;
2475978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2476978e77e7STakashi Iwai 	return 1;
2477978e77e7STakashi Iwai }
2478978e77e7STakashi Iwai 
2479978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2480978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2481978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2482978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2483978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2484978e77e7STakashi Iwai };
2485978e77e7STakashi Iwai 
2486978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2487978e77e7STakashi Iwai {
2488978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2489978e77e7STakashi Iwai 	int i;
2490978e77e7STakashi Iwai 
2491978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2492978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2493978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2494978e77e7STakashi Iwai 			return true;
2495978e77e7STakashi Iwai 	}
2496978e77e7STakashi Iwai 	return false;
2497978e77e7STakashi Iwai }
2498978e77e7STakashi Iwai 
2499978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2500978e77e7STakashi Iwai 			       char *name, size_t name_len)
2501978e77e7STakashi Iwai {
2502978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2503978e77e7STakashi Iwai 	int idx = 0;
2504978e77e7STakashi Iwai 
2505978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2506978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2507978e77e7STakashi Iwai 
2508978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2509978e77e7STakashi Iwai 		;
2510978e77e7STakashi Iwai }
2511978e77e7STakashi Iwai 
25125f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
25135f171baaSTakashi Iwai {
25145f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2515f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
25165f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
25175f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
25185f171baaSTakashi Iwai 			return 2;
25195f171baaSTakashi Iwai 	}
25205f171baaSTakashi Iwai 	return 1;
25215f171baaSTakashi Iwai }
25225f171baaSTakashi Iwai 
2523978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2524978e77e7STakashi Iwai 				 hda_nid_t *pins)
2525978e77e7STakashi Iwai {
2526978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2527978e77e7STakashi Iwai 	int i;
2528978e77e7STakashi Iwai 
2529978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2530978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2531ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
25325f171baaSTakashi Iwai 			continue;
25335f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2534978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2535975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2536978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2537978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2538978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2539978e77e7STakashi Iwai 			if (!knew)
2540978e77e7STakashi Iwai 				return -ENOMEM;
2541978e77e7STakashi Iwai 			knew->private_value = pin;
2542978e77e7STakashi Iwai 		}
2543978e77e7STakashi Iwai 	}
2544978e77e7STakashi Iwai 
2545978e77e7STakashi Iwai 	return 0;
2546978e77e7STakashi Iwai }
2547978e77e7STakashi Iwai 
254829476558STakashi Iwai /*
254929476558STakashi Iwai  * input jack mode
255029476558STakashi Iwai  */
255129476558STakashi Iwai 
255229476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
255329476558STakashi Iwai #define NUM_VREFS	6
255429476558STakashi Iwai 
255529476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
255629476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
255729476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
255829476558STakashi Iwai };
255929476558STakashi Iwai 
256029476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
256129476558STakashi Iwai {
256229476558STakashi Iwai 	unsigned int pincap;
256329476558STakashi Iwai 
256429476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
256529476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
256629476558STakashi Iwai 	/* filter out unusual vrefs */
256729476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
256829476558STakashi Iwai 	return pincap;
256929476558STakashi Iwai }
257029476558STakashi Iwai 
257129476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
257229476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
257329476558STakashi Iwai {
257429476558STakashi Iwai 	unsigned int i, n = 0;
257529476558STakashi Iwai 
257629476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
257729476558STakashi Iwai 		if (vref_caps & (1 << i)) {
257829476558STakashi Iwai 			if (n == item_idx)
257929476558STakashi Iwai 				return i;
258029476558STakashi Iwai 			n++;
258129476558STakashi Iwai 		}
258229476558STakashi Iwai 	}
258329476558STakashi Iwai 	return 0;
258429476558STakashi Iwai }
258529476558STakashi Iwai 
258629476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
258729476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
258829476558STakashi Iwai {
258929476558STakashi Iwai 	unsigned int i, n = 0;
259029476558STakashi Iwai 
259129476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
259229476558STakashi Iwai 		if (i == idx)
259329476558STakashi Iwai 			return n;
259429476558STakashi Iwai 		if (vref_caps & (1 << i))
259529476558STakashi Iwai 			n++;
259629476558STakashi Iwai 	}
259729476558STakashi Iwai 	return 0;
259829476558STakashi Iwai }
259929476558STakashi Iwai 
260029476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
260129476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
260229476558STakashi Iwai {
260329476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
260429476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
260529476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
260629476558STakashi Iwai 
260729476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
260829476558STakashi Iwai 				 vref_texts);
260929476558STakashi Iwai 	/* set the right text */
261029476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
261129476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
261229476558STakashi Iwai 	return 0;
261329476558STakashi Iwai }
261429476558STakashi Iwai 
261529476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
261629476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
261729476558STakashi Iwai {
261829476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
261929476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
262029476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
262129476558STakashi Iwai 	unsigned int idx;
262229476558STakashi Iwai 
262329476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
262429476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
262529476558STakashi Iwai 	return 0;
262629476558STakashi Iwai }
262729476558STakashi Iwai 
262829476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
262929476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
263029476558STakashi Iwai {
263129476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
263229476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
263329476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
263429476558STakashi Iwai 	unsigned int val, idx;
263529476558STakashi Iwai 
263629476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
263729476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
263829476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
263929476558STakashi Iwai 		return 0;
264029476558STakashi Iwai 
264129476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
264229476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
264329476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
264429476558STakashi Iwai 	return 1;
264529476558STakashi Iwai }
264629476558STakashi Iwai 
264729476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
264829476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
264929476558STakashi Iwai 	.info = in_jack_mode_info,
265029476558STakashi Iwai 	.get = in_jack_mode_get,
265129476558STakashi Iwai 	.put = in_jack_mode_put,
265229476558STakashi Iwai };
265329476558STakashi Iwai 
26545f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26555f171baaSTakashi Iwai {
26565f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
26575f171baaSTakashi Iwai 	int nitems = 0;
2658f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
26595f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
26605f171baaSTakashi Iwai 	return nitems ? nitems : 1;
26615f171baaSTakashi Iwai }
26625f171baaSTakashi Iwai 
266329476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
266429476558STakashi Iwai {
266529476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
266629476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2667975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
26685f171baaSTakashi Iwai 	unsigned int defcfg;
26695f171baaSTakashi Iwai 
2670f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2671f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
267229476558STakashi Iwai 
267329476558STakashi Iwai 	/* no jack mode for fixed pins */
267429476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
267529476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
267629476558STakashi Iwai 		return 0;
267729476558STakashi Iwai 
267829476558STakashi Iwai 	/* no multiple vref caps? */
26795f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
268029476558STakashi Iwai 		return 0;
268129476558STakashi Iwai 
268229476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
268329476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
268429476558STakashi Iwai 	if (!knew)
268529476558STakashi Iwai 		return -ENOMEM;
268629476558STakashi Iwai 	knew->private_value = pin;
268729476558STakashi Iwai 	return 0;
268829476558STakashi Iwai }
268929476558STakashi Iwai 
26905f171baaSTakashi Iwai /*
26915f171baaSTakashi Iwai  * HP/mic shared jack mode
26925f171baaSTakashi Iwai  */
26935f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
26945f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
26955f171baaSTakashi Iwai {
26965f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26975f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
26985f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
26995f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27005f171baaSTakashi Iwai 	const char *text = NULL;
27015f171baaSTakashi Iwai 	int idx;
27025f171baaSTakashi Iwai 
27035f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
27045f171baaSTakashi Iwai 	uinfo->count = 1;
27055f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
27065f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
27075f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
27085f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
27095f171baaSTakashi Iwai 	if (idx < out_jacks) {
27105f171baaSTakashi Iwai 		if (out_jacks > 1)
27115f171baaSTakashi Iwai 			text = out_jack_texts[idx];
27125f171baaSTakashi Iwai 		else
27135f171baaSTakashi Iwai 			text = "Headphone Out";
27145f171baaSTakashi Iwai 	} else {
27155f171baaSTakashi Iwai 		idx -= out_jacks;
27165f171baaSTakashi Iwai 		if (in_jacks > 1) {
27175f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27185f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
27195f171baaSTakashi Iwai 		} else
27205f171baaSTakashi Iwai 			text = "Mic In";
27215f171baaSTakashi Iwai 	}
27225f171baaSTakashi Iwai 
27235f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
27245f171baaSTakashi Iwai 	return 0;
27255f171baaSTakashi Iwai }
27265f171baaSTakashi Iwai 
27275f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
27285f171baaSTakashi Iwai {
27295f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27305f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27315f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
27325f171baaSTakashi Iwai 	int idx = 0;
27335f171baaSTakashi Iwai 
27345f171baaSTakashi Iwai 	if (val & PIN_OUT) {
27355f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
27365f171baaSTakashi Iwai 			idx = 1;
27375f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
27385f171baaSTakashi Iwai 		idx = out_jacks;
27395f171baaSTakashi Iwai 		if (in_jacks > 1) {
27405f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27415f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
27425f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
27435f171baaSTakashi Iwai 		}
27445f171baaSTakashi Iwai 	}
27455f171baaSTakashi Iwai 	return idx;
27465f171baaSTakashi Iwai }
27475f171baaSTakashi Iwai 
27485f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
27495f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27505f171baaSTakashi Iwai {
27515f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27525f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27535f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
27545f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
27555f171baaSTakashi Iwai 	return 0;
27565f171baaSTakashi Iwai }
27575f171baaSTakashi Iwai 
27585f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
27595f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27605f171baaSTakashi Iwai {
27615f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27625f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27635f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27645f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27655f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
27665f171baaSTakashi Iwai 
27675f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
27685f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
27695f171baaSTakashi Iwai 	if (oldval == idx)
27705f171baaSTakashi Iwai 		return 0;
27715f171baaSTakashi Iwai 
27725f171baaSTakashi Iwai 	if (idx < out_jacks) {
27735f171baaSTakashi Iwai 		if (out_jacks > 1)
27745f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
27755f171baaSTakashi Iwai 		else
27765f171baaSTakashi Iwai 			val = PIN_HP;
27775f171baaSTakashi Iwai 	} else {
27785f171baaSTakashi Iwai 		idx -= out_jacks;
27795f171baaSTakashi Iwai 		if (in_jacks > 1) {
27805f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27815f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
27823f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
27833f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
27845f171baaSTakashi Iwai 		} else
278516c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
27865f171baaSTakashi Iwai 	}
27875f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2788963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
27898ba955ceSTakashi Iwai 
27905f171baaSTakashi Iwai 	return 1;
27915f171baaSTakashi Iwai }
27925f171baaSTakashi Iwai 
27935f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
27945f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
27955f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
27965f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
27975f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
27985f171baaSTakashi Iwai };
27995f171baaSTakashi Iwai 
28005f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
28015f171baaSTakashi Iwai {
28025f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28035f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
28045f171baaSTakashi Iwai 
28055f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
28065f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
28075f171baaSTakashi Iwai 	if (!knew)
28085f171baaSTakashi Iwai 		return -ENOMEM;
28095f171baaSTakashi Iwai 	knew->private_value = pin;
28108ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
28115f171baaSTakashi Iwai 	return 0;
28125f171baaSTakashi Iwai }
2813352f7f91STakashi Iwai 
2814352f7f91STakashi Iwai /*
2815352f7f91STakashi Iwai  * Parse input paths
2816352f7f91STakashi Iwai  */
2817352f7f91STakashi Iwai 
2818352f7f91STakashi Iwai /* add the powersave loopback-list entry */
28190186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2820352f7f91STakashi Iwai {
2821352f7f91STakashi Iwai 	struct hda_amp_list *list;
2822352f7f91STakashi Iwai 
28230186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
28240186f4f4STakashi Iwai 	if (!list)
28250186f4f4STakashi Iwai 		return -ENOMEM;
2826352f7f91STakashi Iwai 	list->nid = mix;
2827352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2828352f7f91STakashi Iwai 	list->idx = idx;
28290186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
28300186f4f4STakashi Iwai 	return 0;
2831cb53c626STakashi Iwai }
2832cb53c626STakashi Iwai 
28332ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
28342ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
28352ded3e5bSTakashi Iwai  */
28362ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
28372ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
28382ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
28392ded3e5bSTakashi Iwai {
28402ded3e5bSTakashi Iwai 	int idx, num_conns;
28412ded3e5bSTakashi Iwai 	const hda_nid_t *list;
28422ded3e5bSTakashi Iwai 	hda_nid_t nid;
28432ded3e5bSTakashi Iwai 
28442ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
28452ded3e5bSTakashi Iwai 	if (idx < 0)
28462ded3e5bSTakashi Iwai 		return false;
28472ded3e5bSTakashi Iwai 
28482ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
28492ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
28502ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28512ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
28522ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28532ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
28542ded3e5bSTakashi Iwai 		return true;
28552ded3e5bSTakashi Iwai 
28562ded3e5bSTakashi Iwai 	/* check leaf node */
28572ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
28582ded3e5bSTakashi Iwai 	if (num_conns < idx)
28592ded3e5bSTakashi Iwai 		return false;
28602ded3e5bSTakashi Iwai 	nid = list[idx];
286143a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
286243a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
28632ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
286443a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
286543a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
28662ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
28672ded3e5bSTakashi Iwai 
28682ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
28692ded3e5bSTakashi Iwai }
28702ded3e5bSTakashi Iwai 
2871352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2872196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2873196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2874352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
28751da177e4SLinus Torvalds {
2876352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2877352f7f91STakashi Iwai 	struct nid_path *path;
28782ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
2879352f7f91STakashi Iwai 	int err, idx;
28801da177e4SLinus Torvalds 
28812ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
28822ded3e5bSTakashi Iwai 		return 0;
2883352f7f91STakashi Iwai 
28843ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2885352f7f91STakashi Iwai 	if (!path)
2886352f7f91STakashi Iwai 		return -EINVAL;
28870c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2888196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2889352f7f91STakashi Iwai 
2890352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
28912ded3e5bSTakashi Iwai 	if (mix_val) {
28922ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
2893d13bd412STakashi Iwai 		if (err < 0)
28941da177e4SLinus Torvalds 			return err;
28952ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
28961da177e4SLinus Torvalds 	}
28971da177e4SLinus Torvalds 
28982ded3e5bSTakashi Iwai 	if (mute_val) {
28992ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
2900d13bd412STakashi Iwai 		if (err < 0)
29011da177e4SLinus Torvalds 			return err;
29022ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
29031da177e4SLinus Torvalds 	}
29041da177e4SLinus Torvalds 
2905352f7f91STakashi Iwai 	path->active = true;
29060186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
29070186f4f4STakashi Iwai 	if (err < 0)
29080186f4f4STakashi Iwai 		return err;
2909e4a395e7STakashi Iwai 
2910e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
2911e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
2912e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
2913e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
2914e4a395e7STakashi Iwai 		if (path) {
2915e4a395e7STakashi Iwai 			print_nid_path("loopback-merge", path);
2916e4a395e7STakashi Iwai 			path->active = true;
2917e4a395e7STakashi Iwai 			spec->loopback_merge_path =
2918e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
2919e4a395e7STakashi Iwai 		}
2920e4a395e7STakashi Iwai 	}
2921e4a395e7STakashi Iwai 
2922352f7f91STakashi Iwai 	return 0;
29231da177e4SLinus Torvalds }
29241da177e4SLinus Torvalds 
2925352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
29261da177e4SLinus Torvalds {
2927352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2928352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2929352f7f91STakashi Iwai }
2930352f7f91STakashi Iwai 
2931352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2932352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2933352f7f91STakashi Iwai {
2934352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2935352f7f91STakashi Iwai 	hda_nid_t nid;
2936352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2937352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2938352f7f91STakashi Iwai 	int i, nums = 0;
2939352f7f91STakashi Iwai 
2940352f7f91STakashi Iwai 	nid = codec->start_nid;
2941352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2942352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2943352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2944352f7f91STakashi Iwai 
2945352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2946352f7f91STakashi Iwai 			continue;
2947352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2948352f7f91STakashi Iwai 		if (++nums >= max_nums)
2949352f7f91STakashi Iwai 			break;
2950352f7f91STakashi Iwai 	}
2951352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
29520ffd534eSTakashi Iwai 
29530ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
29540ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
29550ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
29560ffd534eSTakashi Iwai 
2957352f7f91STakashi Iwai 	return nums;
2958352f7f91STakashi Iwai }
2959352f7f91STakashi Iwai 
2960352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2961352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2962352f7f91STakashi Iwai  */
2963352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2964352f7f91STakashi Iwai {
2965352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2966352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
29673a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2968352f7f91STakashi Iwai 	int i, n, nums;
2969352f7f91STakashi Iwai 
2970352f7f91STakashi Iwai 	nums = 0;
29713a65bcdcSTakashi Iwai 	ok_bits = 0;
2972352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2973352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
29743a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2975352f7f91STakashi Iwai 				break;
2976352f7f91STakashi Iwai 		}
29773a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
29783a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
29793a65bcdcSTakashi Iwai 			nums++;
29803a65bcdcSTakashi Iwai 		}
2981352f7f91STakashi Iwai 	}
2982352f7f91STakashi Iwai 
29833a65bcdcSTakashi Iwai 	if (!ok_bits) {
2984352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2985352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2986352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
29873a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2988352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2989352f7f91STakashi Iwai 					break;
2990352f7f91STakashi Iwai 				}
2991352f7f91STakashi Iwai 			}
2992352f7f91STakashi Iwai 		}
2993352f7f91STakashi Iwai 
2994352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2995352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2996352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
29973a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
29983a65bcdcSTakashi Iwai 		nums = 0;
29993a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
30003a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
30013a65bcdcSTakashi Iwai 				continue;
30023a65bcdcSTakashi Iwai 			if (n != nums) {
30033a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3004980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3005980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3006980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
30073a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
30083a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
30093a65bcdcSTakashi Iwai 				}
3010980428ceSTakashi Iwai 			}
30113a65bcdcSTakashi Iwai 			nums++;
30123a65bcdcSTakashi Iwai 		}
3013352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3014352f7f91STakashi Iwai 	}
3015352f7f91STakashi Iwai 
3016967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3017967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
3018352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
3019352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3020352f7f91STakashi Iwai 	}
3021352f7f91STakashi Iwai 
3022352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3023352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3024352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3025352f7f91STakashi Iwai 
30261da177e4SLinus Torvalds 	return 0;
30271da177e4SLinus Torvalds }
30281da177e4SLinus Torvalds 
3029f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3030f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
30319dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
30329dba205bSTakashi Iwai 				const char *label, int anchor)
3033f3fc0b0bSTakashi Iwai {
3034f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3035f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3036f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3037f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3038f3fc0b0bSTakashi Iwai 	int c;
3039f3fc0b0bSTakashi Iwai 
3040f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3041f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3042f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3043f3fc0b0bSTakashi Iwai 
3044f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3045f3fc0b0bSTakashi Iwai 			continue;
3046f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3047f3fc0b0bSTakashi Iwai 		if (!path)
3048f3fc0b0bSTakashi Iwai 			continue;
3049f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
3050f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3051f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3052f3fc0b0bSTakashi Iwai 
3053f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3054967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3055967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3056f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
30579dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
3058f3fc0b0bSTakashi Iwai 			imux_added = true;
3059f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3060f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3061f3fc0b0bSTakashi Iwai 		}
3062f3fc0b0bSTakashi Iwai 	}
3063f3fc0b0bSTakashi Iwai 
3064f3fc0b0bSTakashi Iwai 	return 0;
3065f3fc0b0bSTakashi Iwai }
3066f3fc0b0bSTakashi Iwai 
30671da177e4SLinus Torvalds /*
3068352f7f91STakashi Iwai  * create playback/capture controls for input pins
30691da177e4SLinus Torvalds  */
30709dba205bSTakashi Iwai 
3071c970042cSTakashi Iwai /* fill the label for each input at first */
3072c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3073c970042cSTakashi Iwai {
3074c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3075c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3076c970042cSTakashi Iwai 	int i;
3077c970042cSTakashi Iwai 
3078c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3079c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3080c970042cSTakashi Iwai 		const char *label;
3081c970042cSTakashi Iwai 		int j, idx;
3082c970042cSTakashi Iwai 
3083c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3084c970042cSTakashi Iwai 			continue;
3085c970042cSTakashi Iwai 
3086c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3087c970042cSTakashi Iwai 		idx = 0;
30888e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3089c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3090c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3091c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3092c970042cSTakashi Iwai 				break;
3093c970042cSTakashi Iwai 			}
3094c970042cSTakashi Iwai 		}
3095c970042cSTakashi Iwai 
3096c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3097c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3098c970042cSTakashi Iwai 	}
3099c970042cSTakashi Iwai 
3100c970042cSTakashi Iwai 	return 0;
3101c970042cSTakashi Iwai }
3102c970042cSTakashi Iwai 
31039dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
31049dba205bSTakashi Iwai 
3105352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3106a7da6ce5STakashi Iwai {
3107352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3108352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3109352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3110352f7f91STakashi Iwai 	int num_adcs;
3111c970042cSTakashi Iwai 	int i, err;
31122c12c30dSTakashi Iwai 	unsigned int val;
3113a7da6ce5STakashi Iwai 
3114352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3115352f7f91STakashi Iwai 	if (num_adcs < 0)
3116352f7f91STakashi Iwai 		return 0;
3117352f7f91STakashi Iwai 
3118c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3119c970042cSTakashi Iwai 	if (err < 0)
3120c970042cSTakashi Iwai 		return err;
3121c970042cSTakashi Iwai 
3122352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3123352f7f91STakashi Iwai 		hda_nid_t pin;
3124352f7f91STakashi Iwai 
3125352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3126352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3127352f7f91STakashi Iwai 			continue;
3128352f7f91STakashi Iwai 
31292c12c30dSTakashi Iwai 		val = PIN_IN;
31302c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
31312c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
313293c9d8aeSTakashi Iwai 		if (pin != spec->hp_mic_pin)
31332c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
31342c12c30dSTakashi Iwai 
3135352f7f91STakashi Iwai 		if (mixer) {
3136352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3137196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3138c970042cSTakashi Iwai 						       spec->input_labels[i],
3139c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3140c970042cSTakashi Iwai 						       mixer);
3141a7da6ce5STakashi Iwai 				if (err < 0)
3142a7da6ce5STakashi Iwai 					return err;
3143a7da6ce5STakashi Iwai 			}
3144352f7f91STakashi Iwai 		}
3145352f7f91STakashi Iwai 
3146c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3147c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3148f3fc0b0bSTakashi Iwai 		if (err < 0)
3149f3fc0b0bSTakashi Iwai 			return err;
315029476558STakashi Iwai 
3151f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
315229476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
315329476558STakashi Iwai 			if (err < 0)
315429476558STakashi Iwai 				return err;
315529476558STakashi Iwai 		}
3156352f7f91STakashi Iwai 	}
3157f3fc0b0bSTakashi Iwai 
3158f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
3159f1e762ddSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input &&
3160f1e762ddSTakashi Iwai 	    snd_hda_get_bool_hint(codec, "add_stereo_mix_input") > 0) {
31619dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3162f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3163f3fc0b0bSTakashi Iwai 		if (err < 0)
3164f3fc0b0bSTakashi Iwai 			return err;
3165352f7f91STakashi Iwai 	}
3166352f7f91STakashi Iwai 
3167a7da6ce5STakashi Iwai 	return 0;
3168a7da6ce5STakashi Iwai }
3169a7da6ce5STakashi Iwai 
31701da177e4SLinus Torvalds 
3171352f7f91STakashi Iwai /*
3172352f7f91STakashi Iwai  * input source mux
3173352f7f91STakashi Iwai  */
3174352f7f91STakashi Iwai 
3175c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3176c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3177352f7f91STakashi Iwai {
3178352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3179b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3180b56fa1edSDavid Henningsson 		snd_BUG();
3181b56fa1edSDavid Henningsson 		return NULL;
3182b56fa1edSDavid Henningsson 	}
3183352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3184352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3185d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3186b56fa1edSDavid Henningsson 		snd_BUG();
3187b56fa1edSDavid Henningsson 		return NULL;
3188b56fa1edSDavid Henningsson 	}
3189c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
319097ec558aSTakashi Iwai }
3191352f7f91STakashi Iwai 
3192352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3193352f7f91STakashi Iwai 		      unsigned int idx);
3194352f7f91STakashi Iwai 
3195352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3196352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3197352f7f91STakashi Iwai {
3198352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3199352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3200352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3201352f7f91STakashi Iwai }
3202352f7f91STakashi Iwai 
3203352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3204352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3205352f7f91STakashi Iwai {
3206352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3207352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
32082a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
32092a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3210352f7f91STakashi Iwai 
3211352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
32121da177e4SLinus Torvalds 	return 0;
32131da177e4SLinus Torvalds }
32141da177e4SLinus Torvalds 
3215352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3216352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
32171da177e4SLinus Torvalds {
3218352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
32192a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3220352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3221352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3222352f7f91STakashi Iwai }
3223352f7f91STakashi Iwai 
3224352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
32251da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3226352f7f91STakashi Iwai 	.name = "Input Source",
3227352f7f91STakashi Iwai 	.info = mux_enum_info,
3228352f7f91STakashi Iwai 	.get = mux_enum_get,
3229352f7f91STakashi Iwai 	.put = mux_enum_put,
32301da177e4SLinus Torvalds };
3231071c73adSTakashi Iwai 
323247d46abbSTakashi Iwai /*
323347d46abbSTakashi Iwai  * capture volume and capture switch ctls
323447d46abbSTakashi Iwai  */
323547d46abbSTakashi Iwai 
3236352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3237352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3238071c73adSTakashi Iwai 
323947d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3240352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3241352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3242352f7f91STakashi Iwai 			  put_call_t func, int type)
3243352f7f91STakashi Iwai {
3244352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3245352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3246352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3247352f7f91STakashi Iwai 	struct nid_path *path;
3248352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3249071c73adSTakashi Iwai 
3250352f7f91STakashi Iwai 	imux = &spec->input_mux;
3251a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3252352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
325347d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
325447d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
325547d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
325647d46abbSTakashi Iwai 	 */
3257352f7f91STakashi Iwai 	codec->cached_write = 1;
3258352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3259c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3260c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3261352f7f91STakashi Iwai 			continue;
3262352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3263352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3264352f7f91STakashi Iwai 		if (err < 0)
3265352f7f91STakashi Iwai 			goto error;
3266352f7f91STakashi Iwai 	}
3267352f7f91STakashi Iwai  error:
3268352f7f91STakashi Iwai 	codec->cached_write = 0;
3269352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3270dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec); /* flush the updates */
3271352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
3272a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3273352f7f91STakashi Iwai 	return err;
3274352f7f91STakashi Iwai }
3275352f7f91STakashi Iwai 
3276352f7f91STakashi Iwai /* capture volume ctl callbacks */
3277352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3278352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3279352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3280352f7f91STakashi Iwai 
3281352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3282352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3283352f7f91STakashi Iwai {
3284352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3285352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3286352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3287352f7f91STakashi Iwai }
3288352f7f91STakashi Iwai 
3289352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3290352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3291352f7f91STakashi Iwai 	.name = "Capture Volume",
3292352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3293352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3294352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3295352f7f91STakashi Iwai 	.info = cap_vol_info,
3296352f7f91STakashi Iwai 	.get = cap_vol_get,
3297352f7f91STakashi Iwai 	.put = cap_vol_put,
3298352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3299352f7f91STakashi Iwai };
3300352f7f91STakashi Iwai 
3301352f7f91STakashi Iwai /* capture switch ctl callbacks */
3302352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3303352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3304352f7f91STakashi Iwai 
3305352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3306352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3307352f7f91STakashi Iwai {
3308a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3309352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3310352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3311352f7f91STakashi Iwai }
3312352f7f91STakashi Iwai 
3313352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3314352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3315352f7f91STakashi Iwai 	.name = "Capture Switch",
3316352f7f91STakashi Iwai 	.info = cap_sw_info,
3317352f7f91STakashi Iwai 	.get = cap_sw_get,
3318352f7f91STakashi Iwai 	.put = cap_sw_put,
3319352f7f91STakashi Iwai };
3320352f7f91STakashi Iwai 
3321352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3322352f7f91STakashi Iwai {
3323352f7f91STakashi Iwai 	hda_nid_t nid;
3324352f7f91STakashi Iwai 	int i, depth;
3325352f7f91STakashi Iwai 
3326352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3327352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3328352f7f91STakashi Iwai 		if (depth >= path->depth)
3329352f7f91STakashi Iwai 			return -EINVAL;
3330352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3331352f7f91STakashi Iwai 		nid = path->path[i];
3332352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3333352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3334352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3335352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3336352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3337352f7f91STakashi Iwai 				int idx = path->idx[i];
3338352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3339352f7f91STakashi Iwai 					idx = 0;
3340352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3341352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3342352f7f91STakashi Iwai 			}
3343352f7f91STakashi Iwai 		}
3344352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3345352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3346352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3347352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3348352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3349352f7f91STakashi Iwai 				int idx = path->idx[i];
3350352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3351352f7f91STakashi Iwai 					idx = 0;
3352352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3353352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3354352f7f91STakashi Iwai 			}
3355352f7f91STakashi Iwai 		}
3356352f7f91STakashi Iwai 	}
3357352f7f91STakashi Iwai 	return 0;
3358352f7f91STakashi Iwai }
3359352f7f91STakashi Iwai 
3360352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3361352f7f91STakashi Iwai {
3362352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3363352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3364352f7f91STakashi Iwai 	unsigned int val;
3365352f7f91STakashi Iwai 	int i;
3366352f7f91STakashi Iwai 
3367352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3368352f7f91STakashi Iwai 		return false;
3369352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3370352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3371352f7f91STakashi Iwai 			continue;
3372352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3373352f7f91STakashi Iwai 			return false;
3374352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3375352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3376352f7f91STakashi Iwai 	}
3377352f7f91STakashi Iwai 	return false;
3378352f7f91STakashi Iwai }
3379352f7f91STakashi Iwai 
3380a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3381a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3382a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3383a35bd1e3STakashi Iwai {
3384a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3385a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3386a35bd1e3STakashi Iwai 	int ret;
3387a35bd1e3STakashi Iwai 
3388a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3389a35bd1e3STakashi Iwai 	if (ret < 0)
3390a35bd1e3STakashi Iwai 		return ret;
3391a35bd1e3STakashi Iwai 
3392a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
3393a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3394a35bd1e3STakashi Iwai 
3395a35bd1e3STakashi Iwai 	return ret;
3396a35bd1e3STakashi Iwai }
3397a35bd1e3STakashi Iwai 
3398352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3399352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3400352f7f91STakashi Iwai 			      bool inv_dmic)
3401352f7f91STakashi Iwai {
3402352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3403975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3404352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3405352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3406352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3407a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3408352f7f91STakashi Iwai 
3409352f7f91STakashi Iwai 	if (!ctl)
3410352f7f91STakashi Iwai 		return 0;
3411352f7f91STakashi Iwai 
3412352f7f91STakashi Iwai 	if (label)
3413352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3414352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3415352f7f91STakashi Iwai 	else
3416352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3417352f7f91STakashi Iwai 			 "Capture %s", sfx);
3418a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3419352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3420a35bd1e3STakashi Iwai 	if (!knew)
3421a35bd1e3STakashi Iwai 		return -ENOMEM;
3422a90229e0STakashi Iwai 	if (is_switch)
3423a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3424a35bd1e3STakashi Iwai 	if (!inv_dmic)
3425a35bd1e3STakashi Iwai 		return 0;
3426352f7f91STakashi Iwai 
3427352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3428352f7f91STakashi Iwai 	if (label)
3429352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3430352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3431352f7f91STakashi Iwai 	else
3432352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3433352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3434a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3435352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3436a35bd1e3STakashi Iwai 	if (!knew)
3437a35bd1e3STakashi Iwai 		return -ENOMEM;
3438a90229e0STakashi Iwai 	if (is_switch)
3439a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3440a35bd1e3STakashi Iwai 	return 0;
3441352f7f91STakashi Iwai }
3442352f7f91STakashi Iwai 
3443352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3444352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3445352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3446352f7f91STakashi Iwai 				     bool inv_dmic)
3447352f7f91STakashi Iwai {
3448352f7f91STakashi Iwai 	int err;
3449352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3450352f7f91STakashi Iwai 	if (err < 0)
3451352f7f91STakashi Iwai 		return err;
3452352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3453071c73adSTakashi Iwai 	if (err < 0)
3454071c73adSTakashi Iwai 		return err;
3455071c73adSTakashi Iwai 	return 0;
34561da177e4SLinus Torvalds }
3457071c73adSTakashi Iwai 
3458352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3459352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3460352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3461352f7f91STakashi Iwai {
3462352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3463352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3464352f7f91STakashi Iwai 
3465352f7f91STakashi Iwai 	if (vol_ctl) {
346612c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3467352f7f91STakashi Iwai 		if (!knew)
3468352f7f91STakashi Iwai 			return -ENOMEM;
3469352f7f91STakashi Iwai 		knew->index = idx;
3470352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3471352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3472352f7f91STakashi Iwai 	}
3473352f7f91STakashi Iwai 	if (sw_ctl) {
347412c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3475352f7f91STakashi Iwai 		if (!knew)
3476352f7f91STakashi Iwai 			return -ENOMEM;
3477352f7f91STakashi Iwai 		knew->index = idx;
3478352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3479352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3480352f7f91STakashi Iwai 	}
3481352f7f91STakashi Iwai 	return 0;
3482352f7f91STakashi Iwai }
3483352f7f91STakashi Iwai 
3484352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3485352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3486352f7f91STakashi Iwai {
3487352f7f91STakashi Iwai 	struct nid_path *path;
3488352f7f91STakashi Iwai 	unsigned int ctl;
3489352f7f91STakashi Iwai 	int i;
3490352f7f91STakashi Iwai 
3491c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3492352f7f91STakashi Iwai 	if (!path)
3493352f7f91STakashi Iwai 		return 0;
3494352f7f91STakashi Iwai 	ctl = path->ctls[type];
3495352f7f91STakashi Iwai 	if (!ctl)
3496352f7f91STakashi Iwai 		return 0;
3497352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3498c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3499352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3500352f7f91STakashi Iwai 			return 0;
3501352f7f91STakashi Iwai 	}
3502352f7f91STakashi Iwai 	return ctl;
3503352f7f91STakashi Iwai }
3504352f7f91STakashi Iwai 
3505352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3506352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3507352f7f91STakashi Iwai {
3508352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3509352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3510c970042cSTakashi Iwai 	int i, err, type;
3511352f7f91STakashi Iwai 
3512352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3513352f7f91STakashi Iwai 		bool inv_dmic;
3514c970042cSTakashi Iwai 		int idx;
35159dba205bSTakashi Iwai 
3516c970042cSTakashi Iwai 		idx = imux->items[i].index;
3517c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
35189dba205bSTakashi Iwai 			continue;
3519352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3520352f7f91STakashi Iwai 
3521352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3522c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3523c970042cSTakashi Iwai 						 spec->input_labels[idx],
3524c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3525c970042cSTakashi Iwai 						 type,
3526352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3527352f7f91STakashi Iwai 						 inv_dmic);
3528d13bd412STakashi Iwai 			if (err < 0)
3529071c73adSTakashi Iwai 				return err;
3530352f7f91STakashi Iwai 		}
3531352f7f91STakashi Iwai 	}
3532071c73adSTakashi Iwai 	return 0;
3533352f7f91STakashi Iwai }
3534071c73adSTakashi Iwai 
3535352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3536352f7f91STakashi Iwai {
3537352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3538352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3539352f7f91STakashi Iwai 	int i, n, nums, err;
3540352f7f91STakashi Iwai 
3541352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3542352f7f91STakashi Iwai 		nums = 1;
3543352f7f91STakashi Iwai 	else
3544352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3545352f7f91STakashi Iwai 
3546352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3547352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3548624d914dSTakashi Iwai 		const char *name;
3549624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3550624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3551352f7f91STakashi Iwai 		if (!knew)
3552352f7f91STakashi Iwai 			return -ENOMEM;
3553352f7f91STakashi Iwai 		knew->count = nums;
3554352f7f91STakashi Iwai 	}
3555352f7f91STakashi Iwai 
3556352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3557352f7f91STakashi Iwai 		bool multi = false;
355899a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3559352f7f91STakashi Iwai 		bool inv_dmic = false;
3560352f7f91STakashi Iwai 		int vol, sw;
3561352f7f91STakashi Iwai 
3562352f7f91STakashi Iwai 		vol = sw = 0;
3563352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3564352f7f91STakashi Iwai 			struct nid_path *path;
3565c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3566352f7f91STakashi Iwai 			if (!path)
3567352f7f91STakashi Iwai 				continue;
3568352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3569352f7f91STakashi Iwai 			if (!vol)
3570352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
357199a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3572352f7f91STakashi Iwai 				multi = true;
357399a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
357499a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
357599a5592dSDavid Henningsson 					multi_cap_vol = true;
357699a5592dSDavid Henningsson 			}
3577352f7f91STakashi Iwai 			if (!sw)
3578352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
357999a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3580352f7f91STakashi Iwai 				multi = true;
358199a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
358299a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
358399a5592dSDavid Henningsson 					multi_cap_vol = true;
358499a5592dSDavid Henningsson 			}
3585352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3586352f7f91STakashi Iwai 				inv_dmic = true;
3587352f7f91STakashi Iwai 		}
3588352f7f91STakashi Iwai 
3589352f7f91STakashi Iwai 		if (!multi)
3590352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3591352f7f91STakashi Iwai 							inv_dmic);
3592ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3593352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3594352f7f91STakashi Iwai 		else
3595352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3596d13bd412STakashi Iwai 		if (err < 0)
3597071c73adSTakashi Iwai 			return err;
3598071c73adSTakashi Iwai 	}
3599071c73adSTakashi Iwai 
36001da177e4SLinus Torvalds 	return 0;
36011da177e4SLinus Torvalds }
36021da177e4SLinus Torvalds 
3603352f7f91STakashi Iwai /*
3604352f7f91STakashi Iwai  * add mic boosts if needed
3605352f7f91STakashi Iwai  */
36066f7c83afSTakashi Iwai 
36076f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
36086f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
36096f7c83afSTakashi Iwai 			    int dir, int idx)
36106f7c83afSTakashi Iwai {
36116f7c83afSTakashi Iwai 	unsigned int step;
36126f7c83afSTakashi Iwai 
36136f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
36146f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
36156f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
36166f7c83afSTakashi Iwai 		return false;
36176f7c83afSTakashi Iwai 
36186f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
36196f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
36206f7c83afSTakashi Iwai 	if (step < 0x20)
36216f7c83afSTakashi Iwai 		return false;
36226f7c83afSTakashi Iwai 	return true;
36236f7c83afSTakashi Iwai }
36246f7c83afSTakashi Iwai 
36256f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
36266f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
36276f7c83afSTakashi Iwai 				       struct nid_path *path)
36286f7c83afSTakashi Iwai {
36296f7c83afSTakashi Iwai 	unsigned int val = 0;
36306f7c83afSTakashi Iwai 	hda_nid_t nid;
36316f7c83afSTakashi Iwai 	int depth;
36326f7c83afSTakashi Iwai 
36336f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
36346f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
36356f7c83afSTakashi Iwai 			break;
36366f7c83afSTakashi Iwai 		nid = path->path[depth];
36376f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
36386f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
36396f7c83afSTakashi Iwai 			break;
36406f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
36416f7c83afSTakashi Iwai 					   path->idx[depth])) {
36426f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
36436f7c83afSTakashi Iwai 						  HDA_INPUT);
36446f7c83afSTakashi Iwai 			break;
36456f7c83afSTakashi Iwai 		}
36466f7c83afSTakashi Iwai 	}
36476f7c83afSTakashi Iwai 
36486f7c83afSTakashi Iwai 	return val;
36496f7c83afSTakashi Iwai }
36506f7c83afSTakashi Iwai 
3651352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3652352f7f91STakashi Iwai {
3653352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3654352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
36556f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3656a35bd1e3STakashi Iwai 	int i;
3657352f7f91STakashi Iwai 
36586f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
36596f7c83afSTakashi Iwai 		return 0;
36606f7c83afSTakashi Iwai 
36616f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3662352f7f91STakashi Iwai 		struct nid_path *path;
3663352f7f91STakashi Iwai 		unsigned int val;
36646f7c83afSTakashi Iwai 		int idx;
3665975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3666352f7f91STakashi Iwai 
36676f7c83afSTakashi Iwai 		idx = imux->items[i].index;
36686f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
366902aba550SDavid Henningsson 			continue;
367002aba550SDavid Henningsson 
36716f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
36721799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
36736f7c83afSTakashi Iwai 			continue;
36746f7c83afSTakashi Iwai 
36756f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
36766f7c83afSTakashi Iwai 		if (!path)
36776f7c83afSTakashi Iwai 			continue;
36786f7c83afSTakashi Iwai 
36796f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
36806f7c83afSTakashi Iwai 		if (!val)
36816f7c83afSTakashi Iwai 			continue;
36826f7c83afSTakashi Iwai 
36836f7c83afSTakashi Iwai 		/* create a boost control */
3684352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
36856f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3686a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3687a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3688a35bd1e3STakashi Iwai 			return -ENOMEM;
3689352f7f91STakashi Iwai 
3690352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3691352f7f91STakashi Iwai 	}
3692352f7f91STakashi Iwai 	return 0;
3693352f7f91STakashi Iwai }
3694352f7f91STakashi Iwai 
3695352f7f91STakashi Iwai /*
3696352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3697352f7f91STakashi Iwai  */
3698352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3699352f7f91STakashi Iwai {
3700352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
37010c8c0f56STakashi Iwai 	struct nid_path *path;
3702352f7f91STakashi Iwai 	int i, nums;
37032c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3704352f7f91STakashi Iwai 
3705352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3706352f7f91STakashi Iwai 	nums = 0;
3707352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
37082c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3709352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3710352f7f91STakashi Iwai 		if (!dig_nid)
3711352f7f91STakashi Iwai 			continue;
37123ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
37130c8c0f56STakashi Iwai 		if (!path)
3714352f7f91STakashi Iwai 			continue;
37150c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3716e1284af7STakashi Iwai 		path->active = true;
3717196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
37182c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3719352f7f91STakashi Iwai 		if (!nums) {
3720352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3721352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3722352f7f91STakashi Iwai 		} else {
3723352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3724352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3725352f7f91STakashi Iwai 			break;
3726352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3727352f7f91STakashi Iwai 		}
3728352f7f91STakashi Iwai 		nums++;
3729352f7f91STakashi Iwai 	}
3730352f7f91STakashi Iwai 
3731352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
37322c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3733352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3734352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3735352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3736352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3737352f7f91STakashi Iwai 				continue;
3738352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3739352f7f91STakashi Iwai 				continue;
37402c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3741352f7f91STakashi Iwai 			if (path) {
37420c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3743352f7f91STakashi Iwai 				path->active = true;
3744352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
37452430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
37462c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3747352f7f91STakashi Iwai 				break;
3748352f7f91STakashi Iwai 			}
3749352f7f91STakashi Iwai 		}
3750352f7f91STakashi Iwai 	}
3751352f7f91STakashi Iwai }
3752352f7f91STakashi Iwai 
37531da177e4SLinus Torvalds 
37541da177e4SLinus Torvalds /*
3755352f7f91STakashi Iwai  * input MUX handling
37561da177e4SLinus Torvalds  */
37571da177e4SLinus Torvalds 
3758352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3759352f7f91STakashi Iwai 
3760352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3761352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3762352f7f91STakashi Iwai 		      unsigned int idx)
3763352f7f91STakashi Iwai {
3764352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3765352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
376655196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3767352f7f91STakashi Iwai 
3768352f7f91STakashi Iwai 	imux = &spec->input_mux;
3769352f7f91STakashi Iwai 	if (!imux->num_items)
37701da177e4SLinus Torvalds 		return 0;
37711da177e4SLinus Torvalds 
3772352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3773352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3774352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3775352f7f91STakashi Iwai 		return 0;
3776352f7f91STakashi Iwai 
377755196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
377855196fffSTakashi Iwai 	if (!old_path)
3779352f7f91STakashi Iwai 		return 0;
378055196fffSTakashi Iwai 	if (old_path->active)
378155196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3782352f7f91STakashi Iwai 
3783352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3784352f7f91STakashi Iwai 
3785967303daSTakashi Iwai 	if (spec->hp_mic)
3786967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3787352f7f91STakashi Iwai 
3788352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3789352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3790352f7f91STakashi Iwai 
3791c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3792352f7f91STakashi Iwai 	if (!path)
3793352f7f91STakashi Iwai 		return 0;
3794352f7f91STakashi Iwai 	if (path->active)
3795352f7f91STakashi Iwai 		return 0;
3796352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3797352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3798a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
379955196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
38001da177e4SLinus Torvalds 	return 1;
38011da177e4SLinus Torvalds }
38021da177e4SLinus Torvalds 
38031da177e4SLinus Torvalds 
38041da177e4SLinus Torvalds /*
3805352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
38061da177e4SLinus Torvalds  */
3807352f7f91STakashi Iwai 
3808352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3809352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
38101da177e4SLinus Torvalds {
381160ea8ca2STakashi Iwai 	int i;
381260ea8ca2STakashi Iwai 	bool present = false;
38131da177e4SLinus Torvalds 
3814352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3815352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3816352f7f91STakashi Iwai 		if (!nid)
3817352f7f91STakashi Iwai 			break;
38180b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
38190b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
38200b4df931STakashi Iwai 			continue;
382160ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
382260ea8ca2STakashi Iwai 			present = true;
38231da177e4SLinus Torvalds 	}
3824352f7f91STakashi Iwai 	return present;
38251da177e4SLinus Torvalds }
38261da177e4SLinus Torvalds 
3827352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3828352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3829e80c60f3STakashi Iwai 			int *paths, bool mute)
38301da177e4SLinus Torvalds {
3831352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3832352f7f91STakashi Iwai 	int i;
38331da177e4SLinus Torvalds 
3834352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3835352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3836967303daSTakashi Iwai 		unsigned int val, oldval;
3837352f7f91STakashi Iwai 		if (!nid)
3838352f7f91STakashi Iwai 			break;
38397eebffd3STakashi Iwai 
38407eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
3841e80c60f3STakashi Iwai 			struct nid_path *path;
3842e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
3843e80c60f3STakashi Iwai 
3844e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
3845e80c60f3STakashi Iwai 			if (!path)
3846e80c60f3STakashi Iwai 				continue;
3847e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
3848e80c60f3STakashi Iwai 			if (!mute_nid)
3849e80c60f3STakashi Iwai 				continue;
38507eebffd3STakashi Iwai 			if (mute)
3851e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
38527eebffd3STakashi Iwai 			else
3853e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
38547eebffd3STakashi Iwai 			set_pin_eapd(codec, nid, !mute);
38557eebffd3STakashi Iwai 			continue;
38567eebffd3STakashi Iwai 		}
38577eebffd3STakashi Iwai 
3858967303daSTakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
3859967303daSTakashi Iwai 		if (oldval & PIN_IN)
3860967303daSTakashi Iwai 			continue; /* no mute for inputs */
3861352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3862352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3863352f7f91STakashi Iwai 		 */
38642c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
3865967303daSTakashi Iwai 			val = oldval & ~PIN_HP;
38662c12c30dSTakashi Iwai 		else
3867352f7f91STakashi Iwai 			val = 0;
38682c12c30dSTakashi Iwai 		if (!mute)
3869967303daSTakashi Iwai 			val |= oldval;
38702c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
38712c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
38722c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
38732c12c30dSTakashi Iwai 		 * init / resume again
38742c12c30dSTakashi Iwai 		 */
38752c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3876d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3877352f7f91STakashi Iwai 	}
3878352f7f91STakashi Iwai }
38791da177e4SLinus Torvalds 
3880352f7f91STakashi Iwai /* Toggle outputs muting */
38815d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3882352f7f91STakashi Iwai {
3883352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3884e80c60f3STakashi Iwai 	int *paths;
3885352f7f91STakashi Iwai 	int on;
3886352f7f91STakashi Iwai 
3887352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3888352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3889352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3890352f7f91STakashi Iwai 	 */
3891e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3892e80c60f3STakashi Iwai 		paths = spec->out_paths;
3893e80c60f3STakashi Iwai 	else
3894e80c60f3STakashi Iwai 		paths = spec->hp_paths;
3895352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3896e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
3897352f7f91STakashi Iwai 
3898352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3899352f7f91STakashi Iwai 		on = 0;
3900352f7f91STakashi Iwai 	else
3901352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3902352f7f91STakashi Iwai 	on |= spec->master_mute;
390347b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3904e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3905e80c60f3STakashi Iwai 		paths = spec->out_paths;
3906e80c60f3STakashi Iwai 	else
3907e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
3908352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
3909e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
3910352f7f91STakashi Iwai 
3911352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3912352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3913352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3914352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3915352f7f91STakashi Iwai 		return;
3916352f7f91STakashi Iwai 	if (!spec->automute_lo)
3917352f7f91STakashi Iwai 		on = 0;
3918352f7f91STakashi Iwai 	else
3919352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3920352f7f91STakashi Iwai 	on |= spec->master_mute;
392147b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3922e80c60f3STakashi Iwai 	paths = spec->out_paths;
3923352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3924e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
3925352f7f91STakashi Iwai }
39262698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
3927352f7f91STakashi Iwai 
3928352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3929352f7f91STakashi Iwai {
3930352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3931352f7f91STakashi Iwai 	if (spec->automute_hook)
3932352f7f91STakashi Iwai 		spec->automute_hook(codec);
3933352f7f91STakashi Iwai 	else
39345d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
39357eebffd3STakashi Iwai 
39367eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
39377eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
39387eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
3939352f7f91STakashi Iwai }
3940352f7f91STakashi Iwai 
3941352f7f91STakashi Iwai /* standard HP-automute helper */
39425d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3943352f7f91STakashi Iwai {
3944352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
394592603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
394692603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
3947352f7f91STakashi Iwai 
394892603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
394992603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
395092603c59STakashi Iwai 		pins++;
395192603c59STakashi Iwai 		num_pins--;
395292603c59STakashi Iwai 	}
395392603c59STakashi Iwai 
395492603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
3955352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3956352f7f91STakashi Iwai 		return;
3957352f7f91STakashi Iwai 	call_update_outputs(codec);
3958352f7f91STakashi Iwai }
39592698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
3960352f7f91STakashi Iwai 
3961352f7f91STakashi Iwai /* standard line-out-automute helper */
39625d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3963352f7f91STakashi Iwai {
3964352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3965352f7f91STakashi Iwai 
3966352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3967352f7f91STakashi Iwai 		return;
3968352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3969352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3970352f7f91STakashi Iwai 		return;
3971352f7f91STakashi Iwai 
3972352f7f91STakashi Iwai 	spec->line_jack_present =
3973352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3974352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3975352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3976352f7f91STakashi Iwai 		return;
3977352f7f91STakashi Iwai 	call_update_outputs(codec);
3978352f7f91STakashi Iwai }
39792698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
3980352f7f91STakashi Iwai 
3981352f7f91STakashi Iwai /* standard mic auto-switch helper */
39825d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3983352f7f91STakashi Iwai {
3984352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3985352f7f91STakashi Iwai 	int i;
3986352f7f91STakashi Iwai 
3987352f7f91STakashi Iwai 	if (!spec->auto_mic)
3988352f7f91STakashi Iwai 		return;
3989352f7f91STakashi Iwai 
3990352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
39910b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
39920b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
39930b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
39940b4df931STakashi Iwai 			continue;
399560ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
3996352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3997352f7f91STakashi Iwai 			return;
3998352f7f91STakashi Iwai 		}
3999352f7f91STakashi Iwai 	}
4000352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
40011da177e4SLinus Torvalds }
40022698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
40031da177e4SLinus Torvalds 
400477afe0e9STakashi Iwai /* call appropriate hooks */
400577afe0e9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
400677afe0e9STakashi Iwai {
400777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
400877afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
400977afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
401077afe0e9STakashi Iwai 	else
401177afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
401277afe0e9STakashi Iwai }
401377afe0e9STakashi Iwai 
401477afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
401577afe0e9STakashi Iwai 			       struct hda_jack_tbl *jack)
401677afe0e9STakashi Iwai {
401777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
401877afe0e9STakashi Iwai 	if (spec->line_automute_hook)
401977afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
402077afe0e9STakashi Iwai 	else
402177afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
402277afe0e9STakashi Iwai }
402377afe0e9STakashi Iwai 
402477afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
402577afe0e9STakashi Iwai 				struct hda_jack_tbl *jack)
402677afe0e9STakashi Iwai {
402777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
402877afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
402977afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
403077afe0e9STakashi Iwai 	else
403177afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
403277afe0e9STakashi Iwai }
403377afe0e9STakashi Iwai 
4034963afde9STakashi Iwai /* update jack retasking */
4035963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4036963afde9STakashi Iwai {
4037963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4038963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4039963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4040963afde9STakashi Iwai }
4041963afde9STakashi Iwai 
40421da177e4SLinus Torvalds /*
4043352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
40441da177e4SLinus Torvalds  */
4045352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4046352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4047352f7f91STakashi Iwai {
4048352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4049352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4050352f7f91STakashi Iwai 	static const char * const texts3[] = {
4051352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
40521da177e4SLinus Torvalds 	};
40531da177e4SLinus Torvalds 
4054352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4055352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4056352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4057352f7f91STakashi Iwai }
4058352f7f91STakashi Iwai 
4059352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4060352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4061352f7f91STakashi Iwai {
4062352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4063352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4064352f7f91STakashi Iwai 	unsigned int val = 0;
4065352f7f91STakashi Iwai 	if (spec->automute_speaker)
4066352f7f91STakashi Iwai 		val++;
4067352f7f91STakashi Iwai 	if (spec->automute_lo)
4068352f7f91STakashi Iwai 		val++;
4069352f7f91STakashi Iwai 
4070352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4071352f7f91STakashi Iwai 	return 0;
4072352f7f91STakashi Iwai }
4073352f7f91STakashi Iwai 
4074352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4075352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4076352f7f91STakashi Iwai {
4077352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4078352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4079352f7f91STakashi Iwai 
4080352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4081352f7f91STakashi Iwai 	case 0:
4082352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4083352f7f91STakashi Iwai 			return 0;
4084352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4085352f7f91STakashi Iwai 		spec->automute_lo = 0;
4086352f7f91STakashi Iwai 		break;
4087352f7f91STakashi Iwai 	case 1:
4088352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4089352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4090352f7f91STakashi Iwai 				return 0;
4091352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4092352f7f91STakashi Iwai 			spec->automute_lo = 0;
4093352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4094352f7f91STakashi Iwai 			if (spec->automute_lo)
4095352f7f91STakashi Iwai 				return 0;
4096352f7f91STakashi Iwai 			spec->automute_lo = 1;
4097352f7f91STakashi Iwai 		} else
4098352f7f91STakashi Iwai 			return -EINVAL;
4099352f7f91STakashi Iwai 		break;
4100352f7f91STakashi Iwai 	case 2:
4101352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4102352f7f91STakashi Iwai 			return -EINVAL;
4103352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4104352f7f91STakashi Iwai 			return 0;
4105352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4106352f7f91STakashi Iwai 		spec->automute_lo = 1;
4107352f7f91STakashi Iwai 		break;
4108352f7f91STakashi Iwai 	default:
4109352f7f91STakashi Iwai 		return -EINVAL;
4110352f7f91STakashi Iwai 	}
4111352f7f91STakashi Iwai 	call_update_outputs(codec);
4112352f7f91STakashi Iwai 	return 1;
4113352f7f91STakashi Iwai }
4114352f7f91STakashi Iwai 
4115352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4116352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4117352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4118352f7f91STakashi Iwai 	.info = automute_mode_info,
4119352f7f91STakashi Iwai 	.get = automute_mode_get,
4120352f7f91STakashi Iwai 	.put = automute_mode_put,
4121352f7f91STakashi Iwai };
4122352f7f91STakashi Iwai 
4123352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4124352f7f91STakashi Iwai {
4125352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4126352f7f91STakashi Iwai 
412712c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4128352f7f91STakashi Iwai 		return -ENOMEM;
4129352f7f91STakashi Iwai 	return 0;
4130352f7f91STakashi Iwai }
4131352f7f91STakashi Iwai 
4132352f7f91STakashi Iwai /*
4133352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4134352f7f91STakashi Iwai  * Set up appropriately if really supported
4135352f7f91STakashi Iwai  */
4136352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4137352f7f91STakashi Iwai {
4138352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4139352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4140352f7f91STakashi Iwai 	int present = 0;
4141352f7f91STakashi Iwai 	int i, err;
4142352f7f91STakashi Iwai 
4143f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4144f72706beSTakashi Iwai 		return 0;
4145f72706beSTakashi Iwai 
4146352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4147352f7f91STakashi Iwai 		present++;
4148352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4149352f7f91STakashi Iwai 		present++;
4150352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4151352f7f91STakashi Iwai 		present++;
4152352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4153352f7f91STakashi Iwai 		return 0;
4154352f7f91STakashi Iwai 
4155352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4156352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4157352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4158352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4159352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4160352f7f91STakashi Iwai 	}
4161352f7f91STakashi Iwai 
4162352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4163352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4164352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4165352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4166352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4167352f7f91STakashi Iwai 	}
4168352f7f91STakashi Iwai 
4169352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4170352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4171352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4172352f7f91STakashi Iwai 			continue;
4173352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
4174352f7f91STakashi Iwai 			    nid);
4175352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
417677afe0e9STakashi Iwai 						    call_hp_automute);
4177352f7f91STakashi Iwai 		spec->detect_hp = 1;
4178352f7f91STakashi Iwai 	}
4179352f7f91STakashi Iwai 
4180352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4181352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4182352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4183352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4184352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4185352f7f91STakashi Iwai 					continue;
4186352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
4187352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
4188352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
418977afe0e9STakashi Iwai 								    call_line_automute);
4190352f7f91STakashi Iwai 				spec->detect_lo = 1;
4191352f7f91STakashi Iwai 			}
4192352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4193352f7f91STakashi Iwai 	}
4194352f7f91STakashi Iwai 
4195352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4196352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4197352f7f91STakashi Iwai 
4198352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4199352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4200352f7f91STakashi Iwai 
4201352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4202352f7f91STakashi Iwai 		/* create a control for automute mode */
4203352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4204352f7f91STakashi Iwai 		if (err < 0)
4205352f7f91STakashi Iwai 			return err;
4206352f7f91STakashi Iwai 	}
4207352f7f91STakashi Iwai 	return 0;
4208352f7f91STakashi Iwai }
4209352f7f91STakashi Iwai 
4210352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4211352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4212352f7f91STakashi Iwai {
4213352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4214352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4215352f7f91STakashi Iwai 	int i;
4216352f7f91STakashi Iwai 
4217352f7f91STakashi Iwai 	imux = &spec->input_mux;
4218352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4219352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4220352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4221352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4222352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4223352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4224352f7f91STakashi Iwai 	}
4225352f7f91STakashi Iwai 
4226352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4227352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4228352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4229352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
4230352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
423177afe0e9STakashi Iwai 						    call_mic_autoswitch);
4232352f7f91STakashi Iwai 	return true;
4233352f7f91STakashi Iwai }
4234352f7f91STakashi Iwai 
4235352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4236352f7f91STakashi Iwai {
4237352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4238352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4239352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4240352f7f91STakashi Iwai }
4241352f7f91STakashi Iwai 
4242352f7f91STakashi Iwai /*
4243352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4244352f7f91STakashi Iwai  * Set up if really supported
4245352f7f91STakashi Iwai  */
4246352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4247352f7f91STakashi Iwai {
4248352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4249352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4250352f7f91STakashi Iwai 	unsigned int types;
4251352f7f91STakashi Iwai 	int i, num_pins;
4252352f7f91STakashi Iwai 
4253d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4254d12daf6fSTakashi Iwai 		return 0;
4255d12daf6fSTakashi Iwai 
4256352f7f91STakashi Iwai 	types = 0;
4257352f7f91STakashi Iwai 	num_pins = 0;
4258352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4259352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4260352f7f91STakashi Iwai 		unsigned int attr;
4261352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4262352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4263352f7f91STakashi Iwai 		if (types & (1 << attr))
4264352f7f91STakashi Iwai 			return 0; /* already occupied */
4265352f7f91STakashi Iwai 		switch (attr) {
4266352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4267352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4268352f7f91STakashi Iwai 				return 0; /* invalid type */
4269352f7f91STakashi Iwai 			break;
4270352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4271352f7f91STakashi Iwai 			return 0; /* invalid entry */
4272352f7f91STakashi Iwai 		default:
4273352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4274352f7f91STakashi Iwai 				return 0; /* invalid type */
4275352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4276352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4277352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4278352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4279352f7f91STakashi Iwai 				return 0; /* no unsol support */
4280352f7f91STakashi Iwai 			break;
4281352f7f91STakashi Iwai 		}
4282352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4283352f7f91STakashi Iwai 			return 0;
4284352f7f91STakashi Iwai 		types |= (1 << attr);
4285352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4286352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4287352f7f91STakashi Iwai 		num_pins++;
4288352f7f91STakashi Iwai 	}
4289352f7f91STakashi Iwai 
4290352f7f91STakashi Iwai 	if (num_pins < 2)
4291352f7f91STakashi Iwai 		return 0;
4292352f7f91STakashi Iwai 
4293352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4294352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4295352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4296352f7f91STakashi Iwai 	 */
4297352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4298352f7f91STakashi Iwai 	     compare_attr, NULL);
4299352f7f91STakashi Iwai 
4300352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4301352f7f91STakashi Iwai 		return 0;
4302352f7f91STakashi Iwai 
4303352f7f91STakashi Iwai 	spec->auto_mic = 1;
4304352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4305352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
4306352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4307352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4308352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4309352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4310352f7f91STakashi Iwai 
4311352f7f91STakashi Iwai 	return 0;
4312352f7f91STakashi Iwai }
4313352f7f91STakashi Iwai 
431455196fffSTakashi Iwai /* power_filter hook; make inactive widgets into power down */
431555196fffSTakashi Iwai static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
431655196fffSTakashi Iwai 						  hda_nid_t nid,
431755196fffSTakashi Iwai 						  unsigned int power_state)
431855196fffSTakashi Iwai {
431955196fffSTakashi Iwai 	if (power_state != AC_PWRST_D0)
432055196fffSTakashi Iwai 		return power_state;
432155196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
432255196fffSTakashi Iwai 		return power_state;
4323b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
432455196fffSTakashi Iwai 		return power_state;
432555196fffSTakashi Iwai 	return AC_PWRST_D3;
432655196fffSTakashi Iwai }
432755196fffSTakashi Iwai 
4328ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4329ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4330ebb93c05STakashi Iwai {
4331ebb93c05STakashi Iwai 	int i, nums;
4332ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4333ebb93c05STakashi Iwai 	bool has_amp;
4334ebb93c05STakashi Iwai 
4335ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4336ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4337ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4338ebb93c05STakashi Iwai 		if (has_amp)
4339ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, mix,
4340ebb93c05STakashi Iwai 						 HDA_INPUT, i,
4341ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4342ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4343ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, conn[i],
4344ebb93c05STakashi Iwai 						 HDA_OUTPUT, 0,
4345ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4346ebb93c05STakashi Iwai 	}
4347ebb93c05STakashi Iwai }
4348352f7f91STakashi Iwai 
43499eb413e5STakashi Iwai /*
43509eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
43519eb413e5STakashi Iwai  *
43529eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4353352f7f91STakashi Iwai  * or a negative error code
4354352f7f91STakashi Iwai  */
4355352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
43569eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4357352f7f91STakashi Iwai {
4358352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4359352f7f91STakashi Iwai 	int err;
4360352f7f91STakashi Iwai 
43611c70a583STakashi Iwai 	parse_user_hints(codec);
43621c70a583STakashi Iwai 
4363e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4364e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4365e4a395e7STakashi Iwai 
43669eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
43679eb413e5STakashi Iwai 		spec->autocfg = *cfg;
43689eb413e5STakashi Iwai 		cfg = &spec->autocfg;
43699eb413e5STakashi Iwai 	}
43709eb413e5STakashi Iwai 
437198bd1115STakashi Iwai 	if (!spec->main_out_badness)
437298bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
437398bd1115STakashi Iwai 	if (!spec->extra_out_badness)
437498bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
437598bd1115STakashi Iwai 
43766fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
43776fc4cb97SDavid Henningsson 
4378352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4379352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4380352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4381352f7f91STakashi Iwai 			spec->no_analog = 1;
4382352f7f91STakashi Iwai 			goto dig_only;
4383352f7f91STakashi Iwai 		}
4384c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4385352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4386352f7f91STakashi Iwai 	}
4387352f7f91STakashi Iwai 
4388352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4389352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4390352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4391352f7f91STakashi Iwai 		/* use HP as primary out */
4392352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4393352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4394352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4395352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4396352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4397352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4398352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4399352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4400352f7f91STakashi Iwai 	}
4401352f7f91STakashi Iwai 
4402352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4403352f7f91STakashi Iwai 	if (err < 0)
4404352f7f91STakashi Iwai 		return err;
4405352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4406352f7f91STakashi Iwai 	if (err < 0)
4407352f7f91STakashi Iwai 		return err;
4408352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4409352f7f91STakashi Iwai 	if (err < 0)
4410352f7f91STakashi Iwai 		return err;
4411352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4412352f7f91STakashi Iwai 	if (err < 0)
4413352f7f91STakashi Iwai 		return err;
4414352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4415352f7f91STakashi Iwai 	if (err < 0)
4416352f7f91STakashi Iwai 		return err;
441738cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
441838cf6f1aSTakashi Iwai 	if (err < 0)
441938cf6f1aSTakashi Iwai 		return err;
4420c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4421c30aa7b2STakashi Iwai 	if (err < 0)
4422c30aa7b2STakashi Iwai 		return err;
4423967303daSTakashi Iwai 	err = create_hp_mic(codec);
4424352f7f91STakashi Iwai 	if (err < 0)
4425352f7f91STakashi Iwai 		return err;
4426352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4427352f7f91STakashi Iwai 	if (err < 0)
4428352f7f91STakashi Iwai 		return err;
4429352f7f91STakashi Iwai 
4430a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4431a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4432a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4433a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4434a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4435a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4436a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4437a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4438352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4439352f7f91STakashi Iwai 					  spec->const_channel_count);
4440352f7f91STakashi Iwai 
4441352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4442352f7f91STakashi Iwai 	if (err < 0)
4443352f7f91STakashi Iwai 		return err;
4444352f7f91STakashi Iwai 
4445352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4446352f7f91STakashi Iwai 	if (err < 0)
4447352f7f91STakashi Iwai 		return err;
4448352f7f91STakashi Iwai 
4449352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4450352f7f91STakashi Iwai 	if (err < 0)
4451352f7f91STakashi Iwai 		return err;
4452352f7f91STakashi Iwai 
4453f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
4454f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
4455f1e762ddSTakashi Iwai 	    spec->add_stereo_mix_input &&
4456f1e762ddSTakashi Iwai 	    spec->input_mux.num_items > 1 &&
4457f1e762ddSTakashi Iwai 	    snd_hda_get_bool_hint(codec, "add_stereo_mix_input") < 0) {
4458f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
4459f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
4460f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
4461f1e762ddSTakashi Iwai 		if (err < 0)
4462f1e762ddSTakashi Iwai 			return err;
4463f1e762ddSTakashi Iwai 	}
4464f1e762ddSTakashi Iwai 
4465f1e762ddSTakashi Iwai 
4466352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4467352f7f91STakashi Iwai 	if (err < 0)
4468352f7f91STakashi Iwai 		return err;
4469352f7f91STakashi Iwai 
4470352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4471352f7f91STakashi Iwai 	if (err < 0)
4472352f7f91STakashi Iwai 		return err;
4473352f7f91STakashi Iwai 
4474ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4475ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4476ced4cefcSTakashi Iwai 	 */
4477ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4478ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4479ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4480ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4481ced4cefcSTakashi Iwai 		if (err < 0)
4482ced4cefcSTakashi Iwai 			return err;
4483ced4cefcSTakashi Iwai 	}
4484ced4cefcSTakashi Iwai 
4485f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4486978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4487978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4488978e77e7STakashi Iwai 						    cfg->line_out_pins);
4489978e77e7STakashi Iwai 			if (err < 0)
4490978e77e7STakashi Iwai 				return err;
4491978e77e7STakashi Iwai 		}
4492978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4493978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4494978e77e7STakashi Iwai 						    cfg->hp_pins);
4495978e77e7STakashi Iwai 			if (err < 0)
4496978e77e7STakashi Iwai 				return err;
4497978e77e7STakashi Iwai 		}
4498978e77e7STakashi Iwai 	}
4499978e77e7STakashi Iwai 
4500ebb93c05STakashi Iwai 	/* mute all aamix input initially */
4501ebb93c05STakashi Iwai 	if (spec->mixer_nid)
4502ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
4503ebb93c05STakashi Iwai 
4504352f7f91STakashi Iwai  dig_only:
4505352f7f91STakashi Iwai 	parse_digital(codec);
4506352f7f91STakashi Iwai 
450755196fffSTakashi Iwai 	if (spec->power_down_unused)
450855196fffSTakashi Iwai 		codec->power_filter = snd_hda_gen_path_power_filter;
450955196fffSTakashi Iwai 
45107504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
45117504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
45127504b6cdSTakashi Iwai 		if (err < 0)
45137504b6cdSTakashi Iwai 			return err;
45147504b6cdSTakashi Iwai 	}
45157504b6cdSTakashi Iwai 
4516352f7f91STakashi Iwai 	return 1;
4517352f7f91STakashi Iwai }
45182698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
4519352f7f91STakashi Iwai 
4520352f7f91STakashi Iwai 
4521352f7f91STakashi Iwai /*
4522352f7f91STakashi Iwai  * Build control elements
4523352f7f91STakashi Iwai  */
4524352f7f91STakashi Iwai 
4525352f7f91STakashi Iwai /* slave controls for virtual master */
4526352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4527352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4528352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4529352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4530ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4531ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
4532ee79c69aSTakashi Iwai 	"Headphone Side",
4533352f7f91STakashi Iwai 	NULL,
4534352f7f91STakashi Iwai };
4535352f7f91STakashi Iwai 
4536352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
4537352f7f91STakashi Iwai {
4538352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4539352f7f91STakashi Iwai 	int err;
4540352f7f91STakashi Iwai 
454136502d02STakashi Iwai 	if (spec->kctls.used) {
4542352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
4543352f7f91STakashi Iwai 		if (err < 0)
4544352f7f91STakashi Iwai 			return err;
454536502d02STakashi Iwai 	}
4546352f7f91STakashi Iwai 
4547352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
4548352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
4549352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4550352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4551352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
4552352f7f91STakashi Iwai 		if (err < 0)
4553352f7f91STakashi Iwai 			return err;
4554352f7f91STakashi Iwai 		if (!spec->no_analog) {
4555352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
4556352f7f91STakashi Iwai 							    &spec->multiout);
4557352f7f91STakashi Iwai 			if (err < 0)
4558352f7f91STakashi Iwai 				return err;
4559352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
4560352f7f91STakashi Iwai 		}
4561352f7f91STakashi Iwai 	}
4562352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
4563352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
4564352f7f91STakashi Iwai 		if (err < 0)
4565352f7f91STakashi Iwai 			return err;
4566352f7f91STakashi Iwai 	}
4567352f7f91STakashi Iwai 
4568352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
4569352f7f91STakashi Iwai 	if (!spec->no_analog &&
4570352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
4571352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
45727a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
4573352f7f91STakashi Iwai 					  "Playback Volume");
4574352f7f91STakashi Iwai 		if (err < 0)
4575352f7f91STakashi Iwai 			return err;
4576352f7f91STakashi Iwai 	}
4577352f7f91STakashi Iwai 	if (!spec->no_analog &&
4578352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
4579352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
4580352f7f91STakashi Iwai 					    NULL, slave_pfxs,
4581352f7f91STakashi Iwai 					    "Playback Switch",
4582352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
4583352f7f91STakashi Iwai 		if (err < 0)
4584352f7f91STakashi Iwai 			return err;
4585b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
4586fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
4587fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
4588b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4589b63eae0aSTakashi Iwai 		}
4590352f7f91STakashi Iwai 	}
4591352f7f91STakashi Iwai 
4592352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
4593352f7f91STakashi Iwai 
4594352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
4595352f7f91STakashi Iwai 	if (err < 0)
4596352f7f91STakashi Iwai 		return err;
4597352f7f91STakashi Iwai 
4598352f7f91STakashi Iwai 	return 0;
4599352f7f91STakashi Iwai }
46002698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
4601352f7f91STakashi Iwai 
4602352f7f91STakashi Iwai 
4603352f7f91STakashi Iwai /*
4604352f7f91STakashi Iwai  * PCM definitions
4605352f7f91STakashi Iwai  */
4606352f7f91STakashi Iwai 
4607e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
4608e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
4609e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
4610e6b85f3cSTakashi Iwai 				   int action)
4611e6b85f3cSTakashi Iwai {
4612e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4613e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
4614e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
4615e6b85f3cSTakashi Iwai }
4616e6b85f3cSTakashi Iwai 
4617ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
4618ac2e8736STakashi Iwai 				  struct hda_codec *codec,
4619ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
4620ac2e8736STakashi Iwai 				  int action)
4621ac2e8736STakashi Iwai {
4622ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4623ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
4624ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
4625ac2e8736STakashi Iwai }
4626ac2e8736STakashi Iwai 
4627352f7f91STakashi Iwai /*
4628352f7f91STakashi Iwai  * Analog playback callbacks
4629352f7f91STakashi Iwai  */
4630352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
4631352f7f91STakashi Iwai 			     struct hda_codec *codec,
4632352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
4633352f7f91STakashi Iwai {
4634352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
463538cf6f1aSTakashi Iwai 	int err;
463638cf6f1aSTakashi Iwai 
463738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
463838cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
463938cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
4640352f7f91STakashi Iwai 					     hinfo);
4641e6b85f3cSTakashi Iwai 	if (!err) {
464238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
4643e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4644e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
4645e6b85f3cSTakashi Iwai 	}
464638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
464738cf6f1aSTakashi Iwai 	return err;
4648352f7f91STakashi Iwai }
4649352f7f91STakashi Iwai 
4650352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
465197ec558aSTakashi Iwai 				struct hda_codec *codec,
465297ec558aSTakashi Iwai 				unsigned int stream_tag,
465397ec558aSTakashi Iwai 				unsigned int format,
465497ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
465597ec558aSTakashi Iwai {
4656352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4657e6b85f3cSTakashi Iwai 	int err;
4658e6b85f3cSTakashi Iwai 
4659e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4660352f7f91STakashi Iwai 					       stream_tag, format, substream);
4661e6b85f3cSTakashi Iwai 	if (!err)
4662e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4663e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4664e6b85f3cSTakashi Iwai 	return err;
4665352f7f91STakashi Iwai }
466697ec558aSTakashi Iwai 
4667352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4668352f7f91STakashi Iwai 				struct hda_codec *codec,
4669352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4670352f7f91STakashi Iwai {
4671352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4672e6b85f3cSTakashi Iwai 	int err;
4673e6b85f3cSTakashi Iwai 
4674e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4675e6b85f3cSTakashi Iwai 	if (!err)
4676e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4677e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4678e6b85f3cSTakashi Iwai 	return err;
4679352f7f91STakashi Iwai }
4680352f7f91STakashi Iwai 
468138cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
468238cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
468338cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
468438cf6f1aSTakashi Iwai {
468538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
468638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
468738cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4688e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4689e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
469038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
469138cf6f1aSTakashi Iwai 	return 0;
469238cf6f1aSTakashi Iwai }
469338cf6f1aSTakashi Iwai 
4694ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4695ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4696ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4697ac2e8736STakashi Iwai {
4698ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4699ac2e8736STakashi Iwai 	return 0;
4700ac2e8736STakashi Iwai }
4701ac2e8736STakashi Iwai 
4702ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4703ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4704ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4705ac2e8736STakashi Iwai 			       unsigned int format,
4706ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4707ac2e8736STakashi Iwai {
4708ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4709ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4710ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4711ac2e8736STakashi Iwai 	return 0;
4712ac2e8736STakashi Iwai }
4713ac2e8736STakashi Iwai 
4714ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4715ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4716ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4717ac2e8736STakashi Iwai {
4718ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4719ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4720ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4721ac2e8736STakashi Iwai 	return 0;
4722ac2e8736STakashi Iwai }
4723ac2e8736STakashi Iwai 
4724ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4725ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4726ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4727ac2e8736STakashi Iwai {
4728ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4729ac2e8736STakashi Iwai 	return 0;
4730ac2e8736STakashi Iwai }
4731ac2e8736STakashi Iwai 
473238cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
473338cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
473438cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
473538cf6f1aSTakashi Iwai {
473638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
473738cf6f1aSTakashi Iwai 	int err = 0;
473838cf6f1aSTakashi Iwai 
473938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
474038cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
474138cf6f1aSTakashi Iwai 		err = -EBUSY;
474238cf6f1aSTakashi Iwai 	else
474338cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4744e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4745e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
474638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
474738cf6f1aSTakashi Iwai 	return err;
474838cf6f1aSTakashi Iwai }
474938cf6f1aSTakashi Iwai 
475038cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
475138cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
475238cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
475338cf6f1aSTakashi Iwai {
475438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
475538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
475638cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4757e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4758e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
475938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
476038cf6f1aSTakashi Iwai 	return 0;
476138cf6f1aSTakashi Iwai }
476238cf6f1aSTakashi Iwai 
4763e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4764e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4765e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4766e6b85f3cSTakashi Iwai 				    unsigned int format,
4767e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4768e6b85f3cSTakashi Iwai {
4769e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4770e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4771e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4772e6b85f3cSTakashi Iwai 	return 0;
4773e6b85f3cSTakashi Iwai }
4774e6b85f3cSTakashi Iwai 
4775e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4776e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4777e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4778e6b85f3cSTakashi Iwai {
4779e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4780e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4781e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4782e6b85f3cSTakashi Iwai 	return 0;
4783e6b85f3cSTakashi Iwai }
4784e6b85f3cSTakashi Iwai 
4785352f7f91STakashi Iwai /*
4786352f7f91STakashi Iwai  * Digital out
4787352f7f91STakashi Iwai  */
4788352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4789352f7f91STakashi Iwai 				 struct hda_codec *codec,
4790352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4791352f7f91STakashi Iwai {
4792352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4793352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4794352f7f91STakashi Iwai }
4795352f7f91STakashi Iwai 
4796352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4797352f7f91STakashi Iwai 				    struct hda_codec *codec,
4798352f7f91STakashi Iwai 				    unsigned int stream_tag,
4799352f7f91STakashi Iwai 				    unsigned int format,
4800352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4801352f7f91STakashi Iwai {
4802352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4803352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4804352f7f91STakashi Iwai 					     stream_tag, format, substream);
4805352f7f91STakashi Iwai }
4806352f7f91STakashi Iwai 
4807352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4808352f7f91STakashi Iwai 				    struct hda_codec *codec,
4809352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4810352f7f91STakashi Iwai {
4811352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4812352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4813352f7f91STakashi Iwai }
4814352f7f91STakashi Iwai 
4815352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4816352f7f91STakashi Iwai 				  struct hda_codec *codec,
4817352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4818352f7f91STakashi Iwai {
4819352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4820352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4821352f7f91STakashi Iwai }
4822352f7f91STakashi Iwai 
4823352f7f91STakashi Iwai /*
4824352f7f91STakashi Iwai  * Analog capture
4825352f7f91STakashi Iwai  */
4826ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4827ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4828ac2e8736STakashi Iwai 
4829352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4830352f7f91STakashi Iwai 				   struct hda_codec *codec,
4831352f7f91STakashi Iwai 				   unsigned int stream_tag,
4832352f7f91STakashi Iwai 				   unsigned int format,
4833352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4834352f7f91STakashi Iwai {
4835352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4836352f7f91STakashi Iwai 
4837352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
483897ec558aSTakashi Iwai 				   stream_tag, 0, format);
4839ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4840ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
484197ec558aSTakashi Iwai 	return 0;
484297ec558aSTakashi Iwai }
484397ec558aSTakashi Iwai 
4844352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
484597ec558aSTakashi Iwai 				   struct hda_codec *codec,
484697ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
484797ec558aSTakashi Iwai {
4848352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
484997ec558aSTakashi Iwai 
4850352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4851352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4852ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4853ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
485497ec558aSTakashi Iwai 	return 0;
485597ec558aSTakashi Iwai }
485697ec558aSTakashi Iwai 
4857352f7f91STakashi Iwai /*
4858352f7f91STakashi Iwai  */
4859352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4860352f7f91STakashi Iwai 	.substreams = 1,
4861352f7f91STakashi Iwai 	.channels_min = 2,
4862352f7f91STakashi Iwai 	.channels_max = 8,
4863352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4864352f7f91STakashi Iwai 	.ops = {
4865352f7f91STakashi Iwai 		.open = playback_pcm_open,
486638cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4867352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4868352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4869352f7f91STakashi Iwai 	},
4870352f7f91STakashi Iwai };
4871352f7f91STakashi Iwai 
4872352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4873352f7f91STakashi Iwai 	.substreams = 1,
4874352f7f91STakashi Iwai 	.channels_min = 2,
4875352f7f91STakashi Iwai 	.channels_max = 2,
4876352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4877ac2e8736STakashi Iwai 	.ops = {
4878ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4879ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4880ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4881ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4882ac2e8736STakashi Iwai 	},
4883352f7f91STakashi Iwai };
4884352f7f91STakashi Iwai 
4885352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4886352f7f91STakashi Iwai 	.substreams = 1,
4887352f7f91STakashi Iwai 	.channels_min = 2,
4888352f7f91STakashi Iwai 	.channels_max = 2,
4889352f7f91STakashi Iwai 	/* NID is set in build_pcms */
489038cf6f1aSTakashi Iwai 	.ops = {
489138cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4892e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4893e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4894e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
489538cf6f1aSTakashi Iwai 	},
4896352f7f91STakashi Iwai };
4897352f7f91STakashi Iwai 
4898352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4899352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4900352f7f91STakashi Iwai 	.channels_min = 2,
4901352f7f91STakashi Iwai 	.channels_max = 2,
4902352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4903352f7f91STakashi Iwai 	.ops = {
4904ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4905ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4906352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4907352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4908352f7f91STakashi Iwai 	},
4909352f7f91STakashi Iwai };
4910352f7f91STakashi Iwai 
4911352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4912352f7f91STakashi Iwai 	.substreams = 1,
4913352f7f91STakashi Iwai 	.channels_min = 2,
4914352f7f91STakashi Iwai 	.channels_max = 2,
4915352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4916352f7f91STakashi Iwai 	.ops = {
4917352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4918352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4919352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4920352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4921352f7f91STakashi Iwai 	},
4922352f7f91STakashi Iwai };
4923352f7f91STakashi Iwai 
4924352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4925352f7f91STakashi Iwai 	.substreams = 1,
4926352f7f91STakashi Iwai 	.channels_min = 2,
4927352f7f91STakashi Iwai 	.channels_max = 2,
4928352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4929352f7f91STakashi Iwai };
4930352f7f91STakashi Iwai 
4931352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4932352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4933352f7f91STakashi Iwai 	.substreams = 0,
4934352f7f91STakashi Iwai 	.channels_min = 0,
4935352f7f91STakashi Iwai 	.channels_max = 0,
4936352f7f91STakashi Iwai };
4937352f7f91STakashi Iwai 
4938352f7f91STakashi Iwai /*
4939352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4940352f7f91STakashi Iwai  */
4941352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
49421da177e4SLinus Torvalds {
4943352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4944352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
49451da177e4SLinus Torvalds 
4946352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4947352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4948352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4949352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4950352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4951352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4952352f7f91STakashi Iwai 					   spec->cur_adc_format);
4953352f7f91STakashi Iwai 		return true;
4954352f7f91STakashi Iwai 	}
4955352f7f91STakashi Iwai 	return false;
4956352f7f91STakashi Iwai }
4957352f7f91STakashi Iwai 
4958352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4959352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4960352f7f91STakashi Iwai 				       struct hda_codec *codec,
4961352f7f91STakashi Iwai 				       unsigned int stream_tag,
4962352f7f91STakashi Iwai 				       unsigned int format,
4963352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4964352f7f91STakashi Iwai {
4965352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4966352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4967352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4968352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4969352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
49701da177e4SLinus Torvalds 	return 0;
49711da177e4SLinus Torvalds }
49721da177e4SLinus Torvalds 
4973352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4974352f7f91STakashi Iwai 				       struct hda_codec *codec,
4975352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4976352f7f91STakashi Iwai {
4977352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4978352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4979352f7f91STakashi Iwai 	spec->cur_adc = 0;
4980352f7f91STakashi Iwai 	return 0;
4981352f7f91STakashi Iwai }
4982352f7f91STakashi Iwai 
4983352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4984352f7f91STakashi Iwai 	.substreams = 1,
4985352f7f91STakashi Iwai 	.channels_min = 2,
4986352f7f91STakashi Iwai 	.channels_max = 2,
4987352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4988352f7f91STakashi Iwai 	.ops = {
4989352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4990352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4991352f7f91STakashi Iwai 	},
4992352f7f91STakashi Iwai };
4993352f7f91STakashi Iwai 
4994f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4995f873e536STakashi Iwai 				 const char *chip_name)
4996f873e536STakashi Iwai {
4997f873e536STakashi Iwai 	char *p;
4998f873e536STakashi Iwai 
4999f873e536STakashi Iwai 	if (*str)
5000f873e536STakashi Iwai 		return;
5001f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
5002f873e536STakashi Iwai 
5003f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5004f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5005f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5006f873e536STakashi Iwai 			*p = 0;
5007f873e536STakashi Iwai 			break;
5008f873e536STakashi Iwai 		}
5009f873e536STakashi Iwai 	}
5010f873e536STakashi Iwai 	strlcat(str, sfx, len);
5011f873e536STakashi Iwai }
5012f873e536STakashi Iwai 
5013352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
5014352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5015352f7f91STakashi Iwai {
5016352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5017352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
5018352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
5019352f7f91STakashi Iwai 	bool have_multi_adcs;
5020352f7f91STakashi Iwai 
50211da177e4SLinus Torvalds 	codec->num_pcms = 1;
50221da177e4SLinus Torvalds 	codec->pcm_info = info;
50231da177e4SLinus Torvalds 
5024352f7f91STakashi Iwai 	if (spec->no_analog)
5025352f7f91STakashi Iwai 		goto skip_analog;
5026352f7f91STakashi Iwai 
5027f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5028f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
5029f873e536STakashi Iwai 			     " Analog", codec->chip_name);
5030352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
5031352f7f91STakashi Iwai 
5032352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5033352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
5034352f7f91STakashi Iwai 		if (!p)
5035352f7f91STakashi Iwai 			p = &pcm_analog_playback;
5036352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5037352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
5038352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5039352f7f91STakashi Iwai 			spec->multiout.max_channels;
5040352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5041352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5042352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5043352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5044352f7f91STakashi Iwai 	}
5045352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5046352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
5047352f7f91STakashi Iwai 		if (!p) {
5048352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
5049352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
5050352f7f91STakashi Iwai 			else
5051352f7f91STakashi Iwai 				p = &pcm_analog_capture;
5052352f7f91STakashi Iwai 		}
5053352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5054352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
5055352f7f91STakashi Iwai 	}
5056352f7f91STakashi Iwai 
5057352f7f91STakashi Iwai  skip_analog:
5058352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5059352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5060f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5061352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
5062f873e536STakashi Iwai 				     " Digital", codec->chip_name);
5063352f7f91STakashi Iwai 		codec->num_pcms = 2;
5064352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5065352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
5066352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
5067352f7f91STakashi Iwai 		if (spec->dig_out_type)
5068352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5069352f7f91STakashi Iwai 		else
5070352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5071352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
5072352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
5073352f7f91STakashi Iwai 			if (!p)
5074352f7f91STakashi Iwai 				p = &pcm_digital_playback;
5075352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5076352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
5077352f7f91STakashi Iwai 		}
5078352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
5079352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
5080352f7f91STakashi Iwai 			if (!p)
5081352f7f91STakashi Iwai 				p = &pcm_digital_capture;
5082352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5083352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
5084352f7f91STakashi Iwai 		}
5085352f7f91STakashi Iwai 	}
5086352f7f91STakashi Iwai 
5087352f7f91STakashi Iwai 	if (spec->no_analog)
5088352f7f91STakashi Iwai 		return 0;
5089352f7f91STakashi Iwai 
5090352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5091352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5092352f7f91STakashi Iwai 	 */
5093352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5094352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5095352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5096352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5097a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5098a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
5099a607148fSTakashi Iwai 			     " Alt Analog", codec->chip_name);
5100352f7f91STakashi Iwai 		codec->num_pcms = 3;
5101352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
5102a607148fSTakashi Iwai 		info->name = spec->stream_name_alt_analog;
5103352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
5104352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
5105352f7f91STakashi Iwai 			if (!p)
5106352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
5107352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5108352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
5109352f7f91STakashi Iwai 				spec->alt_dac_nid;
5110352f7f91STakashi Iwai 		} else {
5111352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
5112352f7f91STakashi Iwai 				pcm_null_stream;
5113352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
5114352f7f91STakashi Iwai 		}
5115352f7f91STakashi Iwai 		if (have_multi_adcs) {
5116352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
5117352f7f91STakashi Iwai 			if (!p)
5118352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
5119352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5120352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
5121352f7f91STakashi Iwai 				spec->adc_nids[1];
5122352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5123352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5124352f7f91STakashi Iwai 		} else {
5125352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
5126352f7f91STakashi Iwai 				pcm_null_stream;
5127352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
5128352f7f91STakashi Iwai 		}
51291da177e4SLinus Torvalds 	}
51301da177e4SLinus Torvalds 
51311da177e4SLinus Torvalds 	return 0;
51321da177e4SLinus Torvalds }
51332698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5134352f7f91STakashi Iwai 
5135352f7f91STakashi Iwai 
5136352f7f91STakashi Iwai /*
5137352f7f91STakashi Iwai  * Standard auto-parser initializations
5138352f7f91STakashi Iwai  */
5139352f7f91STakashi Iwai 
5140d4156930STakashi Iwai /* configure the given path as a proper output */
51412c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5142352f7f91STakashi Iwai {
5143352f7f91STakashi Iwai 	struct nid_path *path;
5144d4156930STakashi Iwai 	hda_nid_t pin;
5145352f7f91STakashi Iwai 
5146196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5147d4156930STakashi Iwai 	if (!path || !path->depth)
5148352f7f91STakashi Iwai 		return;
5149d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
51502c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
515165033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
515265033cc8STakashi Iwai 			      aamix_default(codec->spec));
5153e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5154352f7f91STakashi Iwai }
5155352f7f91STakashi Iwai 
5156352f7f91STakashi Iwai /* initialize primary output paths */
5157352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5158352f7f91STakashi Iwai {
5159352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5160352f7f91STakashi Iwai 	int i;
5161352f7f91STakashi Iwai 
5162d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
51632c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5164352f7f91STakashi Iwai }
5165352f7f91STakashi Iwai 
5166db23fd19STakashi Iwai 
51672c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5168352f7f91STakashi Iwai {
5169352f7f91STakashi Iwai 	int i;
5170352f7f91STakashi Iwai 
5171d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
51722c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5173352f7f91STakashi Iwai }
5174db23fd19STakashi Iwai 
5175db23fd19STakashi Iwai /* initialize hp and speaker paths */
5176db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5177db23fd19STakashi Iwai {
5178db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5179db23fd19STakashi Iwai 
5180db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
51812c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5182db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5183db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
51842c12c30dSTakashi Iwai 				 spec->speaker_paths);
5185352f7f91STakashi Iwai }
5186352f7f91STakashi Iwai 
5187352f7f91STakashi Iwai /* initialize multi-io paths */
5188352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5189352f7f91STakashi Iwai {
5190352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5191352f7f91STakashi Iwai 	int i;
5192352f7f91STakashi Iwai 
5193352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5194352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5195352f7f91STakashi Iwai 		struct nid_path *path;
5196196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5197352f7f91STakashi Iwai 		if (!path)
5198352f7f91STakashi Iwai 			continue;
5199352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5200352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
52012c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
520265033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
520365033cc8STakashi Iwai 				      aamix_default(spec));
5204352f7f91STakashi Iwai 	}
5205352f7f91STakashi Iwai }
5206352f7f91STakashi Iwai 
52074f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
52084f7f67fbSTakashi Iwai {
52094f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
52104f7f67fbSTakashi Iwai 
52114f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
52124f7f67fbSTakashi Iwai 		return;
52134f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
52144f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
52154f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
52164f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
52174f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
52184f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
52194f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
52204f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
52214f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
52224f7f67fbSTakashi Iwai }
52234f7f67fbSTakashi Iwai 
5224352f7f91STakashi Iwai /* set up input pins and loopback paths */
5225352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5226352f7f91STakashi Iwai {
5227352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5228352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5229352f7f91STakashi Iwai 	int i;
5230352f7f91STakashi Iwai 
5231352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5232352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5233352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
52342c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5235352f7f91STakashi Iwai 
5236352f7f91STakashi Iwai 		/* init loopback inputs */
5237352f7f91STakashi Iwai 		if (spec->mixer_nid) {
52383e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
52393e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5240352f7f91STakashi Iwai 		}
5241352f7f91STakashi Iwai 	}
5242352f7f91STakashi Iwai }
5243352f7f91STakashi Iwai 
5244352f7f91STakashi Iwai /* initialize ADC paths */
5245352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5246352f7f91STakashi Iwai {
5247352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5248352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5249352f7f91STakashi Iwai 	struct nid_path *path;
5250352f7f91STakashi Iwai 	int i, c, nums;
5251352f7f91STakashi Iwai 
5252352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5253352f7f91STakashi Iwai 		nums = 1;
5254352f7f91STakashi Iwai 	else
5255352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5256352f7f91STakashi Iwai 
5257352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5258352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5259c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5260352f7f91STakashi Iwai 			if (path) {
5261352f7f91STakashi Iwai 				bool active = path->active;
5262352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5263352f7f91STakashi Iwai 					active = true;
5264352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5265352f7f91STakashi Iwai 			}
5266352f7f91STakashi Iwai 		}
5267967303daSTakashi Iwai 		if (spec->hp_mic)
5268967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5269352f7f91STakashi Iwai 	}
5270352f7f91STakashi Iwai 
5271352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
5272a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
5273352f7f91STakashi Iwai }
5274352f7f91STakashi Iwai 
5275352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5276352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5277352f7f91STakashi Iwai {
5278352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5279352f7f91STakashi Iwai 	int i;
5280352f7f91STakashi Iwai 	hda_nid_t pin;
5281352f7f91STakashi Iwai 
5282d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
52832c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5284352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
52852430d7b7STakashi Iwai 	if (pin) {
52862c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
52873e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
52882430d7b7STakashi Iwai 	}
5289352f7f91STakashi Iwai }
5290352f7f91STakashi Iwai 
5291973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5292973e4972STakashi Iwai  * invalid unsol tags by some reason
5293973e4972STakashi Iwai  */
5294973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5295973e4972STakashi Iwai {
5296973e4972STakashi Iwai 	int i;
5297973e4972STakashi Iwai 
5298973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5299973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5300973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5301973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5302973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5303973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5304973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5305973e4972STakashi Iwai 	}
5306973e4972STakashi Iwai }
5307973e4972STakashi Iwai 
53085187ac16STakashi Iwai /*
53095187ac16STakashi Iwai  * initialize the generic spec;
53105187ac16STakashi Iwai  * this can be put as patch_ops.init function
53115187ac16STakashi Iwai  */
5312352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5313352f7f91STakashi Iwai {
5314352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5315352f7f91STakashi Iwai 
5316352f7f91STakashi Iwai 	if (spec->init_hook)
5317352f7f91STakashi Iwai 		spec->init_hook(codec);
5318352f7f91STakashi Iwai 
5319352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5320352f7f91STakashi Iwai 
53213bbcd274STakashi Iwai 	codec->cached_write = 1;
53223bbcd274STakashi Iwai 
5323352f7f91STakashi Iwai 	init_multi_out(codec);
5324352f7f91STakashi Iwai 	init_extra_out(codec);
5325352f7f91STakashi Iwai 	init_multi_io(codec);
53264f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5327352f7f91STakashi Iwai 	init_analog_input(codec);
5328352f7f91STakashi Iwai 	init_input_src(codec);
5329352f7f91STakashi Iwai 	init_digital(codec);
5330352f7f91STakashi Iwai 
5331973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5332973e4972STakashi Iwai 
5333352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5334a5cc2509STakashi Iwai 	update_automute_all(codec);
5335352f7f91STakashi Iwai 
5336dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec);
53373bbcd274STakashi Iwai 
5338352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5339352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5340352f7f91STakashi Iwai 
5341352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5342352f7f91STakashi Iwai 	return 0;
5343352f7f91STakashi Iwai }
53442698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5345fce52a3bSTakashi Iwai 
53465187ac16STakashi Iwai /*
53475187ac16STakashi Iwai  * free the generic spec;
53485187ac16STakashi Iwai  * this can be put as patch_ops.free function
53495187ac16STakashi Iwai  */
5350fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5351fce52a3bSTakashi Iwai {
53527504b6cdSTakashi Iwai 	snd_hda_detach_beep_device(codec);
5353fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5354fce52a3bSTakashi Iwai 	kfree(codec->spec);
5355fce52a3bSTakashi Iwai 	codec->spec = NULL;
5356fce52a3bSTakashi Iwai }
53572698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
5358fce52a3bSTakashi Iwai 
5359fce52a3bSTakashi Iwai #ifdef CONFIG_PM
53605187ac16STakashi Iwai /*
53615187ac16STakashi Iwai  * check the loopback power save state;
53625187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
53635187ac16STakashi Iwai  */
5364fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5365fce52a3bSTakashi Iwai {
5366fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5367fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5368fce52a3bSTakashi Iwai }
53692698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
5370fce52a3bSTakashi Iwai #endif
5371352f7f91STakashi Iwai 
5372352f7f91STakashi Iwai 
5373352f7f91STakashi Iwai /*
5374352f7f91STakashi Iwai  * the generic codec support
5375352f7f91STakashi Iwai  */
53761da177e4SLinus Torvalds 
5377352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5378352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5379352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5380352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5381fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5382352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
538383012a7cSTakashi Iwai #ifdef CONFIG_PM
5384fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5385cb53c626STakashi Iwai #endif
53861da177e4SLinus Torvalds };
53871da177e4SLinus Torvalds 
53881da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
53891da177e4SLinus Torvalds {
5390352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
53911da177e4SLinus Torvalds 	int err;
53921da177e4SLinus Torvalds 
5393e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5394352f7f91STakashi Iwai 	if (!spec)
53951da177e4SLinus Torvalds 		return -ENOMEM;
5396352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
53971da177e4SLinus Torvalds 	codec->spec = spec;
53981da177e4SLinus Torvalds 
53999eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
54009eb413e5STakashi Iwai 	if (err < 0)
54019eb413e5STakashi Iwai 		return err;
54029eb413e5STakashi Iwai 
54039eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5404352f7f91STakashi Iwai 	if (err < 0)
54051da177e4SLinus Torvalds 		goto error;
54061da177e4SLinus Torvalds 
54071da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
54081da177e4SLinus Torvalds 	return 0;
54091da177e4SLinus Torvalds 
54101da177e4SLinus Torvalds error:
5411fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
54121da177e4SLinus Torvalds 	return err;
54131da177e4SLinus Torvalds }
54142698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_parse_generic_codec);
5415b21bdd0dSTakashi Iwai 
5416b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
5417b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
5418