xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision e7fdd527)
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>
34d89c6c0cSTakashi Iwai #include <sound/tlv.h>
351da177e4SLinus Torvalds #include "hda_codec.h"
361da177e4SLinus Torvalds #include "hda_local.h"
37352f7f91STakashi Iwai #include "hda_auto_parser.h"
38352f7f91STakashi Iwai #include "hda_jack.h"
397504b6cdSTakashi Iwai #include "hda_beep.h"
40352f7f91STakashi Iwai #include "hda_generic.h"
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds 
43dda42bd0STakashi Iwai /**
44dda42bd0STakashi Iwai  * snd_hda_gen_spec_init - initialize hda_gen_spec struct
45dda42bd0STakashi Iwai  * @spec: hda_gen_spec object to initialize
46dda42bd0STakashi Iwai  *
47dda42bd0STakashi Iwai  * Initialize the given hda_gen_spec object.
48dda42bd0STakashi Iwai  */
49352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
501da177e4SLinus Torvalds {
51352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
52352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
530186f4f4STakashi Iwai 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
5438cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
55352f7f91STakashi Iwai 	return 0;
56352f7f91STakashi Iwai }
572698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
581da177e4SLinus Torvalds 
59dda42bd0STakashi Iwai /**
60dda42bd0STakashi Iwai  * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
61dda42bd0STakashi Iwai  * @spec: hda_gen_spec object
62dda42bd0STakashi Iwai  * @name: name string to override the template, NULL if unchanged
63dda42bd0STakashi Iwai  * @temp: template for the new kctl
64dda42bd0STakashi Iwai  *
65dda42bd0STakashi Iwai  * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
66dda42bd0STakashi Iwai  * element based on the given snd_kcontrol_new template @temp and the
67dda42bd0STakashi Iwai  * name string @name to the list in @spec.
68dda42bd0STakashi Iwai  * Returns the newly created object or NULL as error.
69dda42bd0STakashi Iwai  */
7012c93df6STakashi Iwai struct snd_kcontrol_new *
7112c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
72352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
73352f7f91STakashi Iwai {
74352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
75352f7f91STakashi Iwai 	if (!knew)
76352f7f91STakashi Iwai 		return NULL;
77352f7f91STakashi Iwai 	*knew = *temp;
78352f7f91STakashi Iwai 	if (name)
79352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
80352f7f91STakashi Iwai 	else if (knew->name)
81352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
82352f7f91STakashi Iwai 	if (!knew->name)
83352f7f91STakashi Iwai 		return NULL;
84352f7f91STakashi Iwai 	return knew;
85352f7f91STakashi Iwai }
862698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
87352f7f91STakashi Iwai 
88352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
89352f7f91STakashi Iwai {
90352f7f91STakashi Iwai 	if (spec->kctls.list) {
91352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
92352f7f91STakashi Iwai 		int i;
93352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
94352f7f91STakashi Iwai 			kfree(kctl[i].name);
95352f7f91STakashi Iwai 	}
96352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
97352f7f91STakashi Iwai }
98352f7f91STakashi Iwai 
99a8dca460STakashi Iwai static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
100352f7f91STakashi Iwai {
1011da177e4SLinus Torvalds 	if (!spec)
1021da177e4SLinus Torvalds 		return;
103352f7f91STakashi Iwai 	free_kctls(spec);
104352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1050186f4f4STakashi Iwai 	snd_array_free(&spec->loopback_list);
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds /*
1091c70a583STakashi Iwai  * store user hints
1101c70a583STakashi Iwai  */
1111c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
1121c70a583STakashi Iwai {
1131c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1141c70a583STakashi Iwai 	int val;
1151c70a583STakashi Iwai 
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1221c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1231c70a583STakashi Iwai 	if (val >= 0)
1241c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1251c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1261c70a583STakashi Iwai 	if (val >= 0)
1271c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1281c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1291c70a583STakashi Iwai 	if (val >= 0)
1301c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1311c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1321c70a583STakashi Iwai 	if (val >= 0)
1331c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1341c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1351c70a583STakashi Iwai 	if (val >= 0)
1361c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1371c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1381c70a583STakashi Iwai 	if (val >= 0)
1391c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1401c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1411c70a583STakashi Iwai 	if (val >= 0)
1421c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
143967b1307STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_save_node");
144e6feb5d0STakashi Iwai 	if (val >= 0)
145967b1307STakashi Iwai 		codec->power_save_node = !!val;
1461c70a583STakashi Iwai 
147f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
148f72706beSTakashi Iwai 	if (val >= 0)
149f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1531c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1541c70a583STakashi Iwai 	if (val >= 0)
1551c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1567eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1577eebffd3STakashi Iwai 	if (val >= 0)
1587eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1591c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1601c70a583STakashi Iwai 	if (val >= 0)
1611c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1621c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1631c70a583STakashi Iwai 	if (val >= 0)
1641c70a583STakashi Iwai 		spec->no_primary_hp = !val;
165da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
166da96fb5bSTakashi Iwai 	if (val >= 0)
167da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1681c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1691c70a583STakashi Iwai 	if (val >= 0)
1701c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1711c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1721c70a583STakashi Iwai 	if (val >= 0)
1731c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1741c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1751c70a583STakashi Iwai 	if (val >= 0)
1761c70a583STakashi Iwai 		spec->indep_hp = !!val;
1771c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1781c70a583STakashi Iwai 	if (val >= 0)
1791c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
180f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1811c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1821c70a583STakashi Iwai 	if (val >= 0)
183f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
18429476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
18529476558STakashi Iwai 	if (val >= 0)
186f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
187f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
188f811c3cfSTakashi Iwai 	if (val >= 0)
189f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
19055196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
19155196fffSTakashi Iwai 	if (val >= 0)
19255196fffSTakashi Iwai 		spec->power_down_unused = !!val;
193967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
194967303daSTakashi Iwai 	if (val >= 0)
195967303daSTakashi Iwai 		spec->hp_mic = !!val;
196967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
197967303daSTakashi Iwai 	if (val >= 0)
198967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1991c70a583STakashi Iwai 
2001c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
2011c70a583STakashi Iwai 		spec->mixer_nid = val;
2021c70a583STakashi Iwai }
2031c70a583STakashi Iwai 
2041c70a583STakashi Iwai /*
2052c12c30dSTakashi Iwai  * pin control value accesses
2062c12c30dSTakashi Iwai  */
2072c12c30dSTakashi Iwai 
2082c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
2092c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
2102c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
2112c12c30dSTakashi Iwai 
2122c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
2132c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
2142c12c30dSTakashi Iwai {
2152c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
2162c12c30dSTakashi Iwai }
2172c12c30dSTakashi Iwai 
2182c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2192c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2202c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2212c12c30dSTakashi Iwai {
2222c12c30dSTakashi Iwai 	if (!pin)
2232c12c30dSTakashi Iwai 		return;
2242c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2252c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2262c12c30dSTakashi Iwai 	if (do_write)
2272c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2282c12c30dSTakashi Iwai }
2292c12c30dSTakashi Iwai 
2302c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2312c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2322c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2332c12c30dSTakashi Iwai {
2342c12c30dSTakashi Iwai 	int i;
2352c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2362c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2372c12c30dSTakashi Iwai }
2382c12c30dSTakashi Iwai 
2392c12c30dSTakashi Iwai /*
240352f7f91STakashi Iwai  * parsing paths
2411da177e4SLinus Torvalds  */
2421da177e4SLinus Torvalds 
2433ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2443ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2453ca529d3STakashi Iwai {
2463ca529d3STakashi Iwai 	int i;
2473ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2483ca529d3STakashi Iwai 		if (list[i] == nid)
2493ca529d3STakashi Iwai 			return i;
2503ca529d3STakashi Iwai 	return -1;
2513ca529d3STakashi Iwai }
2523ca529d3STakashi Iwai 
2533ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2543ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2553ca529d3STakashi Iwai {
2563ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2573ca529d3STakashi Iwai }
2583ca529d3STakashi Iwai 
259f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
260f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2613ca529d3STakashi Iwai 				     int anchor_nid)
2621da177e4SLinus Torvalds {
263352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
264352f7f91STakashi Iwai 	int i;
2651da177e4SLinus Torvalds 
266352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
267352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
268352f7f91STakashi Iwai 		if (path->depth <= 0)
269352f7f91STakashi Iwai 			continue;
270352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
271f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2723ca529d3STakashi Iwai 			if (!anchor_nid ||
2733ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2743ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
275352f7f91STakashi Iwai 				return path;
2761da177e4SLinus Torvalds 		}
277f5172a7eSTakashi Iwai 	}
2781da177e4SLinus Torvalds 	return NULL;
2791da177e4SLinus Torvalds }
280f5172a7eSTakashi Iwai 
281dda42bd0STakashi Iwai /**
282dda42bd0STakashi Iwai  * snd_hda_get_path_idx - get the index number corresponding to the path
283dda42bd0STakashi Iwai  * instance
284dda42bd0STakashi Iwai  * @codec: the HDA codec
285dda42bd0STakashi Iwai  * @path: nid_path object
286dda42bd0STakashi Iwai  *
287dda42bd0STakashi Iwai  * The returned index starts from 1, i.e. the actual array index with offset 1,
288dda42bd0STakashi Iwai  * and zero is handled as an invalid path
289196c1766STakashi Iwai  */
290196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
291196c1766STakashi Iwai {
292196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
293196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
294196c1766STakashi Iwai 	ssize_t idx;
295196c1766STakashi Iwai 
296196c1766STakashi Iwai 	if (!spec->paths.used)
297196c1766STakashi Iwai 		return 0;
298196c1766STakashi Iwai 	idx = path - array;
299196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
300196c1766STakashi Iwai 		return 0;
301196c1766STakashi Iwai 	return idx + 1;
302196c1766STakashi Iwai }
3032698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
304196c1766STakashi Iwai 
305dda42bd0STakashi Iwai /**
306dda42bd0STakashi Iwai  * snd_hda_get_path_from_idx - get the path instance corresponding to the
307dda42bd0STakashi Iwai  * given index number
308dda42bd0STakashi Iwai  * @codec: the HDA codec
309dda42bd0STakashi Iwai  * @idx: the path index
310dda42bd0STakashi Iwai  */
311196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
312196c1766STakashi Iwai {
313196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
314196c1766STakashi Iwai 
315196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
316196c1766STakashi Iwai 		return NULL;
317196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
318196c1766STakashi Iwai }
3192698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
320196c1766STakashi Iwai 
321352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
322352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3231da177e4SLinus Torvalds {
324352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
325352f7f91STakashi Iwai 	int i;
326352f7f91STakashi Iwai 
327352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
328352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
329352f7f91STakashi Iwai 		if (path->path[0] == nid)
330352f7f91STakashi Iwai 			return true;
331352f7f91STakashi Iwai 	}
332352f7f91STakashi Iwai 	return false;
3331da177e4SLinus Torvalds }
3341da177e4SLinus Torvalds 
335352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
336352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
337352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3381da177e4SLinus Torvalds {
339352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
340352f7f91STakashi Iwai 		return false;
341352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3421da177e4SLinus Torvalds }
3431da177e4SLinus Torvalds 
344352f7f91STakashi Iwai /* nid, dir and idx */
345352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
346352f7f91STakashi Iwai 
347352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
348352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3491da177e4SLinus Torvalds {
350352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
351352f7f91STakashi Iwai 	int i;
352352f7f91STakashi Iwai 
353352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
354352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
355352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
356352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
357352f7f91STakashi Iwai 			return true;
358352f7f91STakashi Iwai 	}
359352f7f91STakashi Iwai 	return false;
3601da177e4SLinus Torvalds }
3611da177e4SLinus Torvalds 
362352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
363352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3648999bf0aSTakashi Iwai 			      int dir, int idx, int type)
365cb53c626STakashi Iwai {
366352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3678999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
368cb53c626STakashi Iwai }
369352f7f91STakashi Iwai 
3704e76a883STakashi Iwai static void print_nid_path(struct hda_codec *codec,
3714e76a883STakashi Iwai 			   const char *pfx, struct nid_path *path)
3720c8c0f56STakashi Iwai {
3730c8c0f56STakashi Iwai 	char buf[40];
374d82353e5SJoe Perches 	char *pos = buf;
3750c8c0f56STakashi Iwai 	int i;
3760c8c0f56STakashi Iwai 
377d82353e5SJoe Perches 	*pos = 0;
378d82353e5SJoe Perches 	for (i = 0; i < path->depth; i++)
379d82353e5SJoe Perches 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
380d82353e5SJoe Perches 				 pos != buf ? ":" : "",
381d82353e5SJoe Perches 				 path->path[i]);
3820c8c0f56STakashi Iwai 
383d82353e5SJoe Perches 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
3840c8c0f56STakashi Iwai }
3850c8c0f56STakashi Iwai 
386352f7f91STakashi Iwai /* called recursively */
387352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
388352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3893ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3903ca529d3STakashi Iwai 			     int depth)
391352f7f91STakashi Iwai {
392ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
393352f7f91STakashi Iwai 	int i, nums;
394352f7f91STakashi Iwai 
3953ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3963ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3973ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3983ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
399352f7f91STakashi Iwai 
400ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
401352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
402352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
403352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
404352f7f91STakashi Iwai 			 * try to find an empty DAC
405352f7f91STakashi Iwai 			 */
406352f7f91STakashi Iwai 			if (from_nid ||
407352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
408352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
409352f7f91STakashi Iwai 				continue;
410352f7f91STakashi Iwai 		}
4113ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
4123ca529d3STakashi Iwai 		if (anchor_nid <= 0)
413352f7f91STakashi Iwai 			goto found;
414352f7f91STakashi Iwai 	}
415352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
416352f7f91STakashi Iwai 		return false;
417352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
418352f7f91STakashi Iwai 		unsigned int type;
419352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
420352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
421352f7f91STakashi Iwai 		    type == AC_WID_PIN)
422352f7f91STakashi Iwai 			continue;
423352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4243ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
425352f7f91STakashi Iwai 			goto found;
426352f7f91STakashi Iwai 	}
427352f7f91STakashi Iwai 	return false;
428352f7f91STakashi Iwai 
429352f7f91STakashi Iwai  found:
430352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
431352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
432352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
433352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
434352f7f91STakashi Iwai 	path->depth++;
435352f7f91STakashi Iwai 	return true;
436352f7f91STakashi Iwai }
437352f7f91STakashi Iwai 
438c4a58c30STakashi Iwai /*
439dda42bd0STakashi Iwai  * snd_hda_parse_nid_path - parse the widget path from the given nid to
440dda42bd0STakashi Iwai  * the target nid
441dda42bd0STakashi Iwai  * @codec: the HDA codec
442dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
443dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
444dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication
445dda42bd0STakashi Iwai  * @path: the path object to store the result
446dda42bd0STakashi Iwai  *
447dda42bd0STakashi Iwai  * Returns true if a matching path is found.
448dda42bd0STakashi Iwai  *
449dda42bd0STakashi Iwai  * The parsing behavior depends on parameters:
450352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4513ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4523ca529d3STakashi Iwai  * with the given value are evaluated.
4533ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4543ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4553ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
456352f7f91STakashi Iwai  */
457c4a58c30STakashi Iwai static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4583ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
459352f7f91STakashi Iwai 			    struct nid_path *path)
460352f7f91STakashi Iwai {
4613ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
462352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
463352f7f91STakashi Iwai 		path->depth++;
464352f7f91STakashi Iwai 		return true;
465352f7f91STakashi Iwai 	}
466352f7f91STakashi Iwai 	return false;
467352f7f91STakashi Iwai }
468352f7f91STakashi Iwai 
469dda42bd0STakashi Iwai /**
470dda42bd0STakashi Iwai  * snd_hda_add_new_path - parse the path between the given NIDs and
471dda42bd0STakashi Iwai  * add to the path list
472dda42bd0STakashi Iwai  * @codec: the HDA codec
473dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
474dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
475dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
476dda42bd0STakashi Iwai  *
477dda42bd0STakashi Iwai  * If no valid path is found, returns NULL.
478352f7f91STakashi Iwai  */
479352f7f91STakashi Iwai struct nid_path *
480352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4813ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
482352f7f91STakashi Iwai {
483352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
484352f7f91STakashi Iwai 	struct nid_path *path;
485352f7f91STakashi Iwai 
486352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
487352f7f91STakashi Iwai 		return NULL;
488352f7f91STakashi Iwai 
489f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4903ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
491f5172a7eSTakashi Iwai 	if (path)
492f5172a7eSTakashi Iwai 		return path;
493f5172a7eSTakashi Iwai 
494352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
495352f7f91STakashi Iwai 	if (!path)
496352f7f91STakashi Iwai 		return NULL;
497352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4983ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
499352f7f91STakashi Iwai 		return path;
500352f7f91STakashi Iwai 	/* push back */
501352f7f91STakashi Iwai 	spec->paths.used--;
502352f7f91STakashi Iwai 	return NULL;
503352f7f91STakashi Iwai }
5042698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
505352f7f91STakashi Iwai 
506980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
507980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
508980428ceSTakashi Iwai {
509980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
510980428ceSTakashi Iwai 	if (!path)
511980428ceSTakashi Iwai 		return;
512980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
513980428ceSTakashi Iwai }
514980428ceSTakashi Iwai 
5153690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
5163690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
5173690739bSTakashi Iwai {
5183690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5193690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
5203690739bSTakashi Iwai 
5213690739bSTakashi Iwai 	if (!list)
5223690739bSTakashi Iwai 		return 0;
5233690739bSTakashi Iwai 	for (; *list; list += 2)
5243690739bSTakashi Iwai 		if (*list == pin)
5253690739bSTakashi Iwai 			return list[1];
5263690739bSTakashi Iwai 	return 0;
5273690739bSTakashi Iwai }
5283690739bSTakashi Iwai 
529352f7f91STakashi Iwai /* look for an empty DAC slot */
530352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
531352f7f91STakashi Iwai 			      bool is_digital)
532352f7f91STakashi Iwai {
533352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
534352f7f91STakashi Iwai 	bool cap_digital;
535352f7f91STakashi Iwai 	int i;
536352f7f91STakashi Iwai 
537352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
538352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
539352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
540352f7f91STakashi Iwai 			continue;
541352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
542352f7f91STakashi Iwai 		if (is_digital != cap_digital)
543352f7f91STakashi Iwai 			continue;
544352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
545352f7f91STakashi Iwai 			return nid;
546352f7f91STakashi Iwai 	}
547352f7f91STakashi Iwai 	return 0;
548352f7f91STakashi Iwai }
549352f7f91STakashi Iwai 
550352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
551352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
552352f7f91STakashi Iwai {
553352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
554352f7f91STakashi Iwai 	val |= chs << 16;
555352f7f91STakashi Iwai 	return val;
556352f7f91STakashi Iwai }
557352f7f91STakashi Iwai 
55899a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
55999a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
56099a5592dSDavid Henningsson {
56199a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
56299a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
56399a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
56499a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
56599a5592dSDavid Henningsson }
56699a5592dSDavid Henningsson 
567352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
568352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
569352f7f91STakashi Iwai 				       struct nid_path *path)
570352f7f91STakashi Iwai {
571352f7f91STakashi Iwai 	int i;
572352f7f91STakashi Iwai 
573352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
574352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
575352f7f91STakashi Iwai 			return path->path[i];
576352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
577352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
578352f7f91STakashi Iwai 			return path->path[i];
579352f7f91STakashi Iwai 	}
580352f7f91STakashi Iwai 	return 0;
581352f7f91STakashi Iwai }
582352f7f91STakashi Iwai 
583352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
584352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
585352f7f91STakashi Iwai 				      struct nid_path *path)
586352f7f91STakashi Iwai {
587a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
588352f7f91STakashi Iwai 	int i;
589352f7f91STakashi Iwai 
590352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
591a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
592a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
593a1114a8cSTakashi Iwai 			continue;
594a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
595a1114a8cSTakashi Iwai 			return nid;
596352f7f91STakashi Iwai 	}
597352f7f91STakashi Iwai 	return 0;
598352f7f91STakashi Iwai }
599352f7f91STakashi Iwai 
600352f7f91STakashi Iwai /*
601352f7f91STakashi Iwai  * path activation / deactivation
602352f7f91STakashi Iwai  */
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai /* can have the amp-in capability? */
605352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
606352f7f91STakashi Iwai {
607352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
608352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
609352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
610352f7f91STakashi Iwai 
611352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
612352f7f91STakashi Iwai 		return false;
613352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
614352f7f91STakashi Iwai 		return false;
615352f7f91STakashi Iwai 	return true;
616352f7f91STakashi Iwai }
617352f7f91STakashi Iwai 
618352f7f91STakashi Iwai /* can have the amp-out capability? */
619352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
620352f7f91STakashi Iwai {
621352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
622352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
623352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
624352f7f91STakashi Iwai 
625352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
626352f7f91STakashi Iwai 		return false;
627352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
628352f7f91STakashi Iwai 		return false;
629352f7f91STakashi Iwai 	return true;
630352f7f91STakashi Iwai }
631352f7f91STakashi Iwai 
632352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
633352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6347dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
635352f7f91STakashi Iwai {
636352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
637e6feb5d0STakashi Iwai 	int type = get_wcaps_type(get_wcaps(codec, nid));
638352f7f91STakashi Iwai 	int i, n;
639352f7f91STakashi Iwai 
6407639a06cSTakashi Iwai 	if (nid == codec->core.afg)
6415ccf835cSTakashi Iwai 		return true;
6425ccf835cSTakashi Iwai 
643352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
644352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
645352f7f91STakashi Iwai 		if (!path->active)
646352f7f91STakashi Iwai 			continue;
647967b1307STakashi Iwai 		if (codec->power_save_node) {
648e6feb5d0STakashi Iwai 			if (!path->stream_enabled)
649e6feb5d0STakashi Iwai 				continue;
650e6feb5d0STakashi Iwai 			/* ignore unplugged paths except for DAC/ADC */
6516b275b14STakashi Iwai 			if (!(path->pin_enabled || path->pin_fixed) &&
652e6feb5d0STakashi Iwai 			    type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
653e6feb5d0STakashi Iwai 				continue;
654e6feb5d0STakashi Iwai 		}
655352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
656352f7f91STakashi Iwai 			if (path->path[i] == nid) {
6579d2b48f7STakashi Iwai 				if (dir == HDA_OUTPUT || idx == -1 ||
6589d2b48f7STakashi Iwai 				    path->idx[i] == idx)
659352f7f91STakashi Iwai 					return true;
660352f7f91STakashi Iwai 				break;
661352f7f91STakashi Iwai 			}
662352f7f91STakashi Iwai 		}
663352f7f91STakashi Iwai 	}
664352f7f91STakashi Iwai 	return false;
665352f7f91STakashi Iwai }
666352f7f91STakashi Iwai 
667b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
668b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
6699d2b48f7STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, -1)
670b1b9fbd0STakashi Iwai 
671352f7f91STakashi Iwai /* get the default amp value for the target state */
672352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6738999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
674352f7f91STakashi Iwai {
675352f7f91STakashi Iwai 	unsigned int val = 0;
676352f7f91STakashi Iwai 
677352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
678352f7f91STakashi Iwai 		/* set to 0dB */
679352f7f91STakashi Iwai 		if (enable)
680352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
681352f7f91STakashi Iwai 	}
682f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
683352f7f91STakashi Iwai 		if (!enable)
684352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
685352f7f91STakashi Iwai 	}
686352f7f91STakashi Iwai 	return val;
687352f7f91STakashi Iwai }
688352f7f91STakashi Iwai 
689cc261738STakashi Iwai /* is this a stereo widget or a stereo-to-mono mix? */
690cc261738STakashi Iwai static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
691cc261738STakashi Iwai {
692cc261738STakashi Iwai 	unsigned int wcaps = get_wcaps(codec, nid);
693cc261738STakashi Iwai 	hda_nid_t conn;
694cc261738STakashi Iwai 
695cc261738STakashi Iwai 	if (wcaps & AC_WCAP_STEREO)
696cc261738STakashi Iwai 		return true;
697cc261738STakashi Iwai 	if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
698cc261738STakashi Iwai 		return false;
699cc261738STakashi Iwai 	if (snd_hda_get_num_conns(codec, nid) != 1)
700cc261738STakashi Iwai 		return false;
701cc261738STakashi Iwai 	if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
702cc261738STakashi Iwai 		return false;
703cc261738STakashi Iwai 	return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
704cc261738STakashi Iwai }
705cc261738STakashi Iwai 
706352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
707352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
708352f7f91STakashi Iwai {
7098999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
7108999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
711ef403edbSTakashi Iwai 
712cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
713352f7f91STakashi Iwai 		snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
714ef403edbSTakashi Iwai 	else
715ef403edbSTakashi Iwai 		snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
716ef403edbSTakashi Iwai }
717ef403edbSTakashi Iwai 
718ef403edbSTakashi Iwai /* update the amp, doing in stereo or mono depending on NID */
719ef403edbSTakashi Iwai static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
720ef403edbSTakashi Iwai 		      unsigned int mask, unsigned int val)
721ef403edbSTakashi Iwai {
722cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
723ef403edbSTakashi Iwai 		return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
724ef403edbSTakashi Iwai 						mask, val);
725ef403edbSTakashi Iwai 	else
726ef403edbSTakashi Iwai 		return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
727ef403edbSTakashi Iwai 						mask, val);
728352f7f91STakashi Iwai }
729352f7f91STakashi Iwai 
7308999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
7318999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
7328999bf0aSTakashi Iwai  */
7338999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
7348999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
7358999bf0aSTakashi Iwai 					   unsigned int caps)
736352f7f91STakashi Iwai {
7378999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
7388999bf0aSTakashi Iwai 
739f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
7408999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
7418999bf0aSTakashi Iwai 			mask &= ~0x80;
7428999bf0aSTakashi Iwai 	}
7438999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
7448999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
7458999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
7468999bf0aSTakashi Iwai 			mask &= ~0x7f;
7478999bf0aSTakashi Iwai 	}
7488999bf0aSTakashi Iwai 	return mask;
7498999bf0aSTakashi Iwai }
7508999bf0aSTakashi Iwai 
7518999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
7528999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
7538999bf0aSTakashi Iwai {
7548999bf0aSTakashi Iwai 	unsigned int caps;
7558999bf0aSTakashi Iwai 	unsigned int mask, val;
7568999bf0aSTakashi Iwai 
7578999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
7588999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
7598999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
7608999bf0aSTakashi Iwai 	if (!mask)
7618999bf0aSTakashi Iwai 		return;
7628999bf0aSTakashi Iwai 
7638999bf0aSTakashi Iwai 	val &= mask;
764ef403edbSTakashi Iwai 	update_amp(codec, nid, dir, idx, mask, val);
765352f7f91STakashi Iwai }
766352f7f91STakashi Iwai 
767e7fdd527STakashi Iwai static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
768e7fdd527STakashi Iwai 				   int dir, int idx, int idx_to_check,
769e7fdd527STakashi Iwai 				   bool enable)
770e7fdd527STakashi Iwai {
771e7fdd527STakashi Iwai 	/* check whether the given amp is still used by others */
772e7fdd527STakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
773e7fdd527STakashi Iwai 		return;
774e7fdd527STakashi Iwai 	activate_amp(codec, nid, dir, idx, idx_to_check, enable);
775e7fdd527STakashi Iwai }
776e7fdd527STakashi Iwai 
777352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
778352f7f91STakashi Iwai 			     int i, bool enable)
779352f7f91STakashi Iwai {
780352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
781352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
782e7fdd527STakashi Iwai 	check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
783352f7f91STakashi Iwai }
784352f7f91STakashi Iwai 
785352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
786352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
787352f7f91STakashi Iwai {
788352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
789ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
790352f7f91STakashi Iwai 	int n, nums, idx;
791352f7f91STakashi Iwai 	int type;
792352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
793352f7f91STakashi Iwai 
794ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
795352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
796352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
797352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
798352f7f91STakashi Iwai 		nums = 1;
799352f7f91STakashi Iwai 		idx = 0;
800352f7f91STakashi Iwai 	} else
801352f7f91STakashi Iwai 		idx = path->idx[i];
802352f7f91STakashi Iwai 
803352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
804352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
805352f7f91STakashi Iwai 
806352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
807352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
808352f7f91STakashi Iwai 	 */
809352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
810e7fdd527STakashi Iwai 		if (n != idx) {
811e7fdd527STakashi Iwai 			if (conn[n] != spec->mixer_merge_nid)
812352f7f91STakashi Iwai 				continue;
813e7fdd527STakashi Iwai 			/* when aamix is disabled, force to off */
814e7fdd527STakashi Iwai 			if (!add_aamix) {
815e7fdd527STakashi Iwai 				activate_amp(codec, nid, HDA_INPUT, n, n, false);
816e7fdd527STakashi Iwai 				continue;
817e7fdd527STakashi Iwai 			}
818e7fdd527STakashi Iwai 		}
819e7fdd527STakashi Iwai 		check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
820352f7f91STakashi Iwai 	}
821352f7f91STakashi Iwai }
822352f7f91STakashi Iwai 
823e6feb5d0STakashi Iwai /* sync power of each widget in the the given path */
824e6feb5d0STakashi Iwai static hda_nid_t path_power_update(struct hda_codec *codec,
825e6feb5d0STakashi Iwai 				   struct nid_path *path,
826e6feb5d0STakashi Iwai 				   bool allow_powerdown)
827e6feb5d0STakashi Iwai {
828e6feb5d0STakashi Iwai 	hda_nid_t nid, changed = 0;
829e6feb5d0STakashi Iwai 	int i, state;
830e6feb5d0STakashi Iwai 
831e6feb5d0STakashi Iwai 	for (i = 0; i < path->depth; i++) {
832e6feb5d0STakashi Iwai 		nid = path->path[i];
8332206dc94STakashi Iwai 		if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
8342206dc94STakashi Iwai 			continue;
8357639a06cSTakashi Iwai 		if (nid == codec->core.afg)
8365ccf835cSTakashi Iwai 			continue;
837e6feb5d0STakashi Iwai 		if (!allow_powerdown || is_active_nid_for_any(codec, nid))
838e6feb5d0STakashi Iwai 			state = AC_PWRST_D0;
839e6feb5d0STakashi Iwai 		else
840e6feb5d0STakashi Iwai 			state = AC_PWRST_D3;
841e6feb5d0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, state)) {
842e6feb5d0STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
843e6feb5d0STakashi Iwai 					    AC_VERB_SET_POWER_STATE, state);
844e6feb5d0STakashi Iwai 			changed = nid;
84548f4b3a2STakashi Iwai 			/* all known codecs seem to be capable to handl
84648f4b3a2STakashi Iwai 			 * widgets state even in D3, so far.
84748f4b3a2STakashi Iwai 			 * if any new codecs need to restore the widget
84848f4b3a2STakashi Iwai 			 * states after D0 transition, call the function
84948f4b3a2STakashi Iwai 			 * below.
85048f4b3a2STakashi Iwai 			 */
85148f4b3a2STakashi Iwai #if 0 /* disabled */
852d545a57cSTakashi Iwai 			if (state == AC_PWRST_D0)
853d545a57cSTakashi Iwai 				snd_hdac_regmap_sync_node(&codec->core, nid);
85448f4b3a2STakashi Iwai #endif
855e6feb5d0STakashi Iwai 		}
856e6feb5d0STakashi Iwai 	}
857e6feb5d0STakashi Iwai 	return changed;
858e6feb5d0STakashi Iwai }
859e6feb5d0STakashi Iwai 
860e6feb5d0STakashi Iwai /* do sync with the last power state change */
861e6feb5d0STakashi Iwai static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
862e6feb5d0STakashi Iwai {
863e6feb5d0STakashi Iwai 	if (nid) {
864e6feb5d0STakashi Iwai 		msleep(10);
865e6feb5d0STakashi Iwai 		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
866e6feb5d0STakashi Iwai 	}
867e6feb5d0STakashi Iwai }
868e6feb5d0STakashi Iwai 
869dda42bd0STakashi Iwai /**
870dda42bd0STakashi Iwai  * snd_hda_activate_path - activate or deactivate the given path
871dda42bd0STakashi Iwai  * @codec: the HDA codec
872dda42bd0STakashi Iwai  * @path: the path to activate/deactivate
873dda42bd0STakashi Iwai  * @enable: flag to activate or not
874dda42bd0STakashi Iwai  * @add_aamix: enable the input from aamix NID
875dda42bd0STakashi Iwai  *
876dda42bd0STakashi Iwai  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
877352f7f91STakashi Iwai  */
878352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
879352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
880352f7f91STakashi Iwai {
88155196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
882352f7f91STakashi Iwai 	int i;
883352f7f91STakashi Iwai 
884c7cd0ef6STakashi Iwai 	path->active = enable;
885352f7f91STakashi Iwai 
886e6feb5d0STakashi Iwai 	/* make sure the widget is powered up */
887967b1307STakashi Iwai 	if (enable && (spec->power_down_unused || codec->power_save_node))
888967b1307STakashi Iwai 		path_power_update(codec, path, codec->power_save_node);
889e6feb5d0STakashi Iwai 
890352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
89155196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
892e6feb5d0STakashi Iwai 
893352f7f91STakashi Iwai 		if (enable && path->multi[i])
8948f0972dfSTakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
895352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
896352f7f91STakashi Iwai 					    path->idx[i]);
897352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
898352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
899352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
900352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
901352f7f91STakashi Iwai 	}
902352f7f91STakashi Iwai }
9032698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
904352f7f91STakashi Iwai 
90555196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
90655196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
90755196fffSTakashi Iwai {
90855196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
90955196fffSTakashi Iwai 
910967b1307STakashi Iwai 	if (!(spec->power_down_unused || codec->power_save_node) || path->active)
91155196fffSTakashi Iwai 		return;
912e6feb5d0STakashi Iwai 	sync_power_state_change(codec, path_power_update(codec, path, true));
91355196fffSTakashi Iwai }
91455196fffSTakashi Iwai 
915d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
916d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
917d5a9f1bbSTakashi Iwai {
918d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
919d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
920d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
921d5a9f1bbSTakashi Iwai 		return;
92205909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
92305909d5cSTakashi Iwai 		return;
924468ac413STakashi Iwai 	if (codec->inv_eapd)
925468ac413STakashi Iwai 		enable = !enable;
926d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
927d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
928d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
929d5a9f1bbSTakashi Iwai }
930d5a9f1bbSTakashi Iwai 
9313e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
9323e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
9333e367f15STakashi Iwai {
9343e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
9353e367f15STakashi Iwai 	if (path)
9363e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
9373e367f15STakashi Iwai }
9383e367f15STakashi Iwai 
939352f7f91STakashi Iwai 
940352f7f91STakashi Iwai /*
941352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
942352f7f91STakashi Iwai  */
943352f7f91STakashi Iwai 
9447eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
9457eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
946bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
947bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
9487eebffd3STakashi Iwai 
949352f7f91STakashi Iwai enum {
950352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
951352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
952352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
953352f7f91STakashi Iwai };
954352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
955352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
9567eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
9577eebffd3STakashi Iwai 	{
9587eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9597eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
9607eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
9617eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
9627eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
9637eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
9647eebffd3STakashi Iwai 	},
965bc2eee29STakashi Iwai 	{
966bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
967bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
968bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
969bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
970bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
971bc2eee29STakashi Iwai 	},
972352f7f91STakashi Iwai };
973352f7f91STakashi Iwai 
974352f7f91STakashi Iwai /* add dynamic controls from template */
975a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
976a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
977352f7f91STakashi Iwai 		       int cidx, unsigned long val)
978352f7f91STakashi Iwai {
979352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
980352f7f91STakashi Iwai 
98112c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
982352f7f91STakashi Iwai 	if (!knew)
983a35bd1e3STakashi Iwai 		return NULL;
984352f7f91STakashi Iwai 	knew->index = cidx;
985352f7f91STakashi Iwai 	if (get_amp_nid_(val))
986352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
987352f7f91STakashi Iwai 	knew->private_value = val;
988a35bd1e3STakashi Iwai 	return knew;
989352f7f91STakashi Iwai }
990352f7f91STakashi Iwai 
991352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
992352f7f91STakashi Iwai 				const char *pfx, const char *dir,
993352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
994352f7f91STakashi Iwai {
995975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
996352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
997a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
998a35bd1e3STakashi Iwai 		return -ENOMEM;
999a35bd1e3STakashi Iwai 	return 0;
1000352f7f91STakashi Iwai }
1001352f7f91STakashi Iwai 
1002352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1003352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1004352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1005352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1006352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1007352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1008352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1009352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1010352f7f91STakashi Iwai 
1011352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1012352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
1013352f7f91STakashi Iwai {
1014352f7f91STakashi Iwai 	unsigned int val;
1015352f7f91STakashi Iwai 	if (!path)
1016352f7f91STakashi Iwai 		return 0;
1017352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
1018352f7f91STakashi Iwai 	if (!val)
1019352f7f91STakashi Iwai 		return 0;
1020352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1021352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1022352f7f91STakashi Iwai }
1023352f7f91STakashi Iwai 
1024352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
1025352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1026352f7f91STakashi Iwai 			       int type)
1027352f7f91STakashi Iwai {
1028352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
1029352f7f91STakashi Iwai 	if (path) {
1030352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1031352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1032352f7f91STakashi Iwai 			chs = 3; /* stereo */
1033352f7f91STakashi Iwai 	}
1034352f7f91STakashi Iwai 	return chs;
1035352f7f91STakashi Iwai }
1036352f7f91STakashi Iwai 
1037352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1038352f7f91STakashi Iwai 			  struct nid_path *path)
1039352f7f91STakashi Iwai {
1040352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1041352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1042352f7f91STakashi Iwai }
1043352f7f91STakashi Iwai 
1044352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
1045352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1046352f7f91STakashi Iwai  */
1047352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1048352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
1049352f7f91STakashi Iwai {
1050352f7f91STakashi Iwai 	unsigned int val;
1051352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
1052352f7f91STakashi Iwai 
1053352f7f91STakashi Iwai 	if (!path)
1054352f7f91STakashi Iwai 		return 0;
1055352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
1056352f7f91STakashi Iwai 	if (!val)
1057352f7f91STakashi Iwai 		return 0;
1058352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1059352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
1060352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
1061352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
1062352f7f91STakashi Iwai 		if (nums > 1) {
1063352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
1064352f7f91STakashi Iwai 			val |= nums << 19;
1065352f7f91STakashi Iwai 		}
1066352f7f91STakashi Iwai 	}
1067352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1068352f7f91STakashi Iwai }
1069352f7f91STakashi Iwai 
1070352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1071352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1072352f7f91STakashi Iwai {
1073352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1074352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1075352f7f91STakashi Iwai }
1076352f7f91STakashi Iwai 
10777eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1078bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10797eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10807eebffd3STakashi Iwai {
10817eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10827eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10837eebffd3STakashi Iwai 
10847eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10857eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10867eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10877eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10887eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10897eebffd3STakashi Iwai 	}
1090bc2eee29STakashi Iwai }
10917eebffd3STakashi Iwai 
1092bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1093bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1094bc2eee29STakashi Iwai {
1095bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
10967eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
10977eebffd3STakashi Iwai }
10987eebffd3STakashi Iwai 
1099bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1100bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1101bc2eee29STakashi Iwai {
1102bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1103bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
1104bc2eee29STakashi Iwai }
1105bc2eee29STakashi Iwai 
1106247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1107247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1108247d85eeSTakashi Iwai {
1109247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1110247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1111247d85eeSTakashi Iwai }
1112247d85eeSTakashi Iwai 
1113352f7f91STakashi Iwai static const char * const channel_name[4] = {
1114352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1115352f7f91STakashi Iwai };
1116352f7f91STakashi Iwai 
1117352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1118247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1119247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1120352f7f91STakashi Iwai {
1121247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1122352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1123352f7f91STakashi Iwai 
1124352f7f91STakashi Iwai 	*index = 0;
1125352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1126247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1127352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1128352f7f91STakashi Iwai 
1129352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1130352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1131352f7f91STakashi Iwai 	 */
1132352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1133352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1134352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1135352f7f91STakashi Iwai 
1136247d85eeSTakashi Iwai 	/* multi-io channels */
1137247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1138247d85eeSTakashi Iwai 		return channel_name[ch];
1139247d85eeSTakashi Iwai 
1140352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1141352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1142247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1143247d85eeSTakashi Iwai 		 * don't name it as Speaker
1144247d85eeSTakashi Iwai 		 */
1145247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1146247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1147247d85eeSTakashi Iwai 			break;
1148352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1149352f7f91STakashi Iwai 			return "Speaker";
1150352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1151352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1152352f7f91STakashi Iwai 		break;
1153352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1154247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1155247d85eeSTakashi Iwai 		 * don't name it as Headphone
1156247d85eeSTakashi Iwai 		 */
1157247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1158247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1159247d85eeSTakashi Iwai 			break;
1160352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1161352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1162352f7f91STakashi Iwai 			break;
1163352f7f91STakashi Iwai 		*index = ch;
1164352f7f91STakashi Iwai 		return "Headphone";
116503ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
116603ad6a8cSDavid Henningsson 		/* This deals with the case where we have two DACs and
116703ad6a8cSDavid Henningsson 		 * one LO, one HP and one Speaker */
116803ad6a8cSDavid Henningsson 		if (!ch && cfg->speaker_outs && cfg->hp_outs) {
116903ad6a8cSDavid Henningsson 			bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
117003ad6a8cSDavid Henningsson 			bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
117103ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
117203ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
117303ad6a8cSDavid Henningsson 			if (hp_lo_shared)
117403ad6a8cSDavid Henningsson 				return "Headphone+LO";
117503ad6a8cSDavid Henningsson 			if (spk_lo_shared)
117603ad6a8cSDavid Henningsson 				return "Speaker+LO";
117703ad6a8cSDavid Henningsson 		}
1178247d85eeSTakashi Iwai 	}
1179247d85eeSTakashi Iwai 
1180247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1181352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
11823abb4f4dSDavid Henningsson 		return "Line Out";
1183247d85eeSTakashi Iwai 
1184352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1185352f7f91STakashi Iwai 		snd_BUG();
1186352f7f91STakashi Iwai 		return "PCM";
1187352f7f91STakashi Iwai 	}
1188352f7f91STakashi Iwai 
1189352f7f91STakashi Iwai 	return channel_name[ch];
1190352f7f91STakashi Iwai }
1191352f7f91STakashi Iwai 
1192352f7f91STakashi Iwai /*
1193352f7f91STakashi Iwai  * Parse output paths
1194352f7f91STakashi Iwai  */
1195352f7f91STakashi Iwai 
1196352f7f91STakashi Iwai /* badness definition */
1197352f7f91STakashi Iwai enum {
1198352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1199352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1200352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1201352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1202352f7f91STakashi Iwai 	/* No possible multi-ios */
12031d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1204352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1205352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1206352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1207352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1208352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1209352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
121055a63d4dSTakashi Iwai 	/* No independent HP possible */
1211bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1212352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1213352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1214352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1215352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1216352f7f91STakashi Iwai 	/* Volume widget is shared */
1217352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1218352f7f91STakashi Iwai };
1219352f7f91STakashi Iwai 
12200e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1221352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1222352f7f91STakashi Iwai  *
1223352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1224352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1225352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1226352f7f91STakashi Iwai  */
12270e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1228352f7f91STakashi Iwai {
1229d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1230352f7f91STakashi Iwai 	hda_nid_t nid;
1231352f7f91STakashi Iwai 	unsigned int val;
1232352f7f91STakashi Iwai 	int badness = 0;
1233352f7f91STakashi Iwai 
1234352f7f91STakashi Iwai 	if (!path)
1235352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
12360e614dd0STakashi Iwai 
12370e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
12380e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
12390e614dd0STakashi Iwai 		return 0; /* already evaluated */
12400e614dd0STakashi Iwai 
1241352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1242352f7f91STakashi Iwai 	if (nid) {
1243352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1244d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1245d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1246352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1247352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1248352f7f91STakashi Iwai 		else
1249352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1250352f7f91STakashi Iwai 	} else
1251352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1252352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1253352f7f91STakashi Iwai 	if (nid) {
1254352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1255352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1256352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1257352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1258352f7f91STakashi Iwai 		else
1259352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1260352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1261352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1262352f7f91STakashi Iwai 		else
1263352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1264352f7f91STakashi Iwai 	} else
1265352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1266352f7f91STakashi Iwai 	return badness;
1267352f7f91STakashi Iwai }
1268352f7f91STakashi Iwai 
126998bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1270352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1271352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1272352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1273352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1274352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1275352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1276352f7f91STakashi Iwai };
12772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1278352f7f91STakashi Iwai 
127998bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1280352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1281352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1282352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1283352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1284352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1285352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1286352f7f91STakashi Iwai };
12872698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1288352f7f91STakashi Iwai 
12897385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
12907385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
12917385df61STakashi Iwai {
12927385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
12937385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
12947385df61STakashi Iwai 
12957385df61STakashi Iwai 	if (cfg->line_outs > idx)
12967385df61STakashi Iwai 		return spec->private_dac_nids[idx];
12977385df61STakashi Iwai 	idx -= cfg->line_outs;
12987385df61STakashi Iwai 	if (spec->multi_ios > idx)
12997385df61STakashi Iwai 		return spec->multi_io[idx].dac;
13007385df61STakashi Iwai 	return 0;
13017385df61STakashi Iwai }
13027385df61STakashi Iwai 
13037385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
13047385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
13057385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
13067385df61STakashi Iwai {
13077385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
13087385df61STakashi Iwai }
13097385df61STakashi Iwai 
1310352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1311352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1312352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1313196c1766STakashi Iwai 			   int *path_idx,
1314352f7f91STakashi Iwai 			   const struct badness_table *bad)
1315352f7f91STakashi Iwai {
1316352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1317352f7f91STakashi Iwai 	int i, j;
1318352f7f91STakashi Iwai 	int badness = 0;
1319352f7f91STakashi Iwai 	hda_nid_t dac;
1320352f7f91STakashi Iwai 
1321352f7f91STakashi Iwai 	if (!num_outs)
1322352f7f91STakashi Iwai 		return 0;
1323352f7f91STakashi Iwai 
1324352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
13250c8c0f56STakashi Iwai 		struct nid_path *path;
1326352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
13271e0b5286STakashi Iwai 
13280e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
13290e614dd0STakashi Iwai 		if (path) {
13300e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
13311e0b5286STakashi Iwai 			continue;
13321e0b5286STakashi Iwai 		}
13331e0b5286STakashi Iwai 
13343690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
13353690739bSTakashi Iwai 		if (dacs[i]) {
13363690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
13373690739bSTakashi Iwai 				badness += bad->shared_primary;
13383690739bSTakashi Iwai 		}
13393690739bSTakashi Iwai 
13403690739bSTakashi Iwai 		if (!dacs[i])
1341352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1342352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1343980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1344352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1345352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1346352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1347352f7f91STakashi Iwai 					dacs[j] = 0;
1348980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1349196c1766STakashi Iwai 					path_idx[j] = 0;
1350352f7f91STakashi Iwai 					break;
1351352f7f91STakashi Iwai 				}
1352352f7f91STakashi Iwai 			}
1353352f7f91STakashi Iwai 		}
1354352f7f91STakashi Iwai 		dac = dacs[i];
1355352f7f91STakashi Iwai 		if (!dac) {
13567385df61STakashi Iwai 			if (num_outs > 2)
13577385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
13587385df61STakashi Iwai 			if (!dac)
13597385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
13607385df61STakashi Iwai 			if (!dac)
13617385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1362352f7f91STakashi Iwai 			if (dac) {
1363352f7f91STakashi Iwai 				if (!i)
1364352f7f91STakashi Iwai 					badness += bad->shared_primary;
1365352f7f91STakashi Iwai 				else if (i == 1)
1366352f7f91STakashi Iwai 					badness += bad->shared_surr;
1367352f7f91STakashi Iwai 				else
1368352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1369352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1370352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1371352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1372352f7f91STakashi Iwai 			} else if (!i)
1373352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1374352f7f91STakashi Iwai 			else
1375352f7f91STakashi Iwai 				badness += bad->no_dac;
1376352f7f91STakashi Iwai 		}
13771fa335b0STakashi Iwai 		if (!dac)
13781fa335b0STakashi Iwai 			continue;
13793ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1380117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1381b3a8c745STakashi Iwai 			/* try with aamix */
13823ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1383b3a8c745STakashi Iwai 		}
13841fa335b0STakashi Iwai 		if (!path) {
1385352f7f91STakashi Iwai 			dac = dacs[i] = 0;
13861fa335b0STakashi Iwai 			badness += bad->no_dac;
13871fa335b0STakashi Iwai 		} else {
13884e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1389e1284af7STakashi Iwai 			path->active = true;
1390196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
13910e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1392e1284af7STakashi Iwai 		}
1393352f7f91STakashi Iwai 	}
1394352f7f91STakashi Iwai 
1395352f7f91STakashi Iwai 	return badness;
1396352f7f91STakashi Iwai }
1397352f7f91STakashi Iwai 
1398352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1399352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1400352f7f91STakashi Iwai {
1401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1402352f7f91STakashi Iwai 	int i;
1403352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1404352f7f91STakashi Iwai 
1405352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1406352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1407352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1408352f7f91STakashi Iwai 			continue;
1409352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1410352f7f91STakashi Iwai 			if (nid_found)
1411352f7f91STakashi Iwai 				return 0;
1412352f7f91STakashi Iwai 			nid_found = nid;
1413352f7f91STakashi Iwai 		}
1414352f7f91STakashi Iwai 	}
1415352f7f91STakashi Iwai 	return nid_found;
1416352f7f91STakashi Iwai }
1417352f7f91STakashi Iwai 
1418352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1419352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1420352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1421352f7f91STakashi Iwai {
1422352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1423352f7f91STakashi Iwai 
1424352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1425352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1426352f7f91STakashi Iwai 		return false;
1427352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1428352f7f91STakashi Iwai 		return false;
1429352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1430352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1431352f7f91STakashi Iwai 		return false;
1432352f7f91STakashi Iwai 	return true;
1433352f7f91STakashi Iwai }
1434352f7f91STakashi Iwai 
1435e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1436e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1437e22aab7dSTakashi Iwai {
1438e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1439e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1440e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1441e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1442e22aab7dSTakashi Iwai 	int type, i;
1443e22aab7dSTakashi Iwai 	int num_pins = 0;
1444e22aab7dSTakashi Iwai 
1445e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1446e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1447e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1448e22aab7dSTakashi Iwai 				continue;
1449e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1450e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1451e22aab7dSTakashi Iwai 				num_pins++;
1452e22aab7dSTakashi Iwai 		}
1453e22aab7dSTakashi Iwai 	}
1454e22aab7dSTakashi Iwai 	return num_pins;
1455e22aab7dSTakashi Iwai }
1456e22aab7dSTakashi Iwai 
1457352f7f91STakashi Iwai /*
1458352f7f91STakashi Iwai  * multi-io helper
1459352f7f91STakashi Iwai  *
1460352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1461352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1462352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1463352f7f91STakashi Iwai  * the badness value.
1464352f7f91STakashi Iwai  */
1465352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1466352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1467e22aab7dSTakashi Iwai 			  bool hardwired)
1468352f7f91STakashi Iwai {
1469352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1470352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1471e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1472352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1473352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1474352f7f91STakashi Iwai 	int badness = 0;
14750e614dd0STakashi Iwai 	struct nid_path *path;
1476352f7f91STakashi Iwai 
1477352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1478352f7f91STakashi Iwai 	if (old_pins >= 2)
1479352f7f91STakashi Iwai 		goto end_fill;
1480352f7f91STakashi Iwai 
1481e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1482352f7f91STakashi Iwai 	if (num_pins < 2)
1483352f7f91STakashi Iwai 		goto end_fill;
1484352f7f91STakashi Iwai 
1485352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1486352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1487352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1488352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1489352f7f91STakashi Iwai 
1490352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1491352f7f91STakashi Iwai 				continue;
1492352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1493352f7f91STakashi Iwai 				continue;
1494352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1495352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1496352f7f91STakashi Iwai 					break;
1497352f7f91STakashi Iwai 			}
1498352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1499352f7f91STakashi Iwai 				continue;
1500352f7f91STakashi Iwai 
1501352f7f91STakashi Iwai 			if (hardwired)
1502352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1503352f7f91STakashi Iwai 			else if (!dac)
1504352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1505352f7f91STakashi Iwai 			if (!dac) {
1506352f7f91STakashi Iwai 				badness++;
1507352f7f91STakashi Iwai 				continue;
1508352f7f91STakashi Iwai 			}
15093ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
15103ca529d3STakashi Iwai 						    -spec->mixer_nid);
15110c8c0f56STakashi Iwai 			if (!path) {
1512352f7f91STakashi Iwai 				badness++;
1513352f7f91STakashi Iwai 				continue;
1514352f7f91STakashi Iwai 			}
15154e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1516352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1517352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1518196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1519196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1520352f7f91STakashi Iwai 			spec->multi_ios++;
1521352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1522352f7f91STakashi Iwai 				break;
1523352f7f91STakashi Iwai 		}
1524352f7f91STakashi Iwai 	}
1525352f7f91STakashi Iwai  end_fill:
1526352f7f91STakashi Iwai 	if (badness)
1527352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1528352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1529352f7f91STakashi Iwai 		if (hardwired)
1530352f7f91STakashi Iwai 			return 1; /* nothing found */
1531352f7f91STakashi Iwai 		else
1532352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1533352f7f91STakashi Iwai 	}
1534352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1535352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1536352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1537352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1538352f7f91STakashi Iwai 		return badness;
1539352f7f91STakashi Iwai 	}
1540352f7f91STakashi Iwai 
1541352f7f91STakashi Iwai 	/* assign volume and mute controls */
15420e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
15430e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
15440e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
15450e614dd0STakashi Iwai 	}
1546352f7f91STakashi Iwai 
1547352f7f91STakashi Iwai 	return badness;
1548352f7f91STakashi Iwai }
1549352f7f91STakashi Iwai 
1550352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1551352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1552196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1553352f7f91STakashi Iwai {
1554b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1555352f7f91STakashi Iwai 	int i;
1556352f7f91STakashi Iwai 	bool found = false;
1557352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
15580c8c0f56STakashi Iwai 		struct nid_path *path;
1559352f7f91STakashi Iwai 		hda_nid_t dac;
1560352f7f91STakashi Iwai 		if (dacs[i])
1561352f7f91STakashi Iwai 			continue;
1562352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1563352f7f91STakashi Iwai 		if (!dac)
1564352f7f91STakashi Iwai 			continue;
15653ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
15663ca529d3STakashi Iwai 					    -spec->mixer_nid);
1567117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
15683ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
15690c8c0f56STakashi Iwai 		if (path) {
1570352f7f91STakashi Iwai 			dacs[i] = dac;
1571352f7f91STakashi Iwai 			found = true;
15724e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1573e1284af7STakashi Iwai 			path->active = true;
1574196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1575352f7f91STakashi Iwai 		}
1576352f7f91STakashi Iwai 	}
1577352f7f91STakashi Iwai 	return found;
1578352f7f91STakashi Iwai }
1579352f7f91STakashi Iwai 
1580e7fdd527STakashi Iwai static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1581e7fdd527STakashi Iwai {
1582e7fdd527STakashi Iwai 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1583e7fdd527STakashi Iwai 		spec->aamix_out_paths[2];
1584e7fdd527STakashi Iwai }
1585e7fdd527STakashi Iwai 
1586c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1587c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1588c30aa7b2STakashi Iwai {
15893ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1590c30aa7b2STakashi Iwai 	struct nid_path *path;
15915ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1592c30aa7b2STakashi Iwai 
1593c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
15943ca529d3STakashi Iwai 	if (!path || !path->depth ||
15953ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1596c30aa7b2STakashi Iwai 		return 0;
15975ead56f2STakashi Iwai 	path_dac = path->path[0];
15985ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1599f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1600f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1601f87498b6STakashi Iwai 	if (!path) {
16025ead56f2STakashi Iwai 		if (dac != path_dac)
16035ead56f2STakashi Iwai 			dac = path_dac;
1604f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1605f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1606f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1607f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
16085ead56f2STakashi Iwai 		else
16095ead56f2STakashi Iwai 			dac = 0;
1610f87498b6STakashi Iwai 		if (dac)
1611f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
16123ca529d3STakashi Iwai 						    spec->mixer_nid);
1613f87498b6STakashi Iwai 	}
1614c30aa7b2STakashi Iwai 	if (!path)
1615c30aa7b2STakashi Iwai 		return 0;
16164e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1617c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
16186b275b14STakashi Iwai 	path->pin_fixed = true; /* static route */
1619c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1620c30aa7b2STakashi Iwai }
1621c30aa7b2STakashi Iwai 
162255a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
162355a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
162455a63d4dSTakashi Iwai {
162555a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
162655a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
162755a63d4dSTakashi Iwai 	struct nid_path *path;
162855a63d4dSTakashi Iwai 	int i, idx;
162955a63d4dSTakashi Iwai 
163055a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
163155a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
163255a63d4dSTakashi Iwai 	else
163355a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
163455a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
163555a63d4dSTakashi Iwai 	if (!path)
163655a63d4dSTakashi Iwai 		return false;
163755a63d4dSTakashi Iwai 
163855a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
163955a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
164055a63d4dSTakashi Iwai 		return true;
164155a63d4dSTakashi Iwai 
164255a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
164355a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
164455a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
164555a63d4dSTakashi Iwai 			break;
164655a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
164755a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
164855a63d4dSTakashi Iwai 			return false;
164955a63d4dSTakashi Iwai 	}
165055a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
165155a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
165255a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
165355a63d4dSTakashi Iwai 			return false;
165455a63d4dSTakashi Iwai 	}
165555a63d4dSTakashi Iwai 
165655a63d4dSTakashi Iwai 	return true;
165755a63d4dSTakashi Iwai }
165855a63d4dSTakashi Iwai 
1659a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1660a07a949bSTakashi Iwai  * shared dac pointed by the paths
1661a07a949bSTakashi Iwai  */
1662a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1663a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1664a07a949bSTakashi Iwai {
1665a07a949bSTakashi Iwai 	struct nid_path *path;
1666a07a949bSTakashi Iwai 	int i;
1667a07a949bSTakashi Iwai 
1668a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1669a07a949bSTakashi Iwai 		if (dacs[i])
1670a07a949bSTakashi Iwai 			continue;
1671a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1672a07a949bSTakashi Iwai 		if (!path)
1673a07a949bSTakashi Iwai 			continue;
1674a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1675a07a949bSTakashi Iwai 	}
1676a07a949bSTakashi Iwai }
1677a07a949bSTakashi Iwai 
1678352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1679352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1680352f7f91STakashi Iwai 			      bool fill_hardwired,
1681352f7f91STakashi Iwai 			      bool fill_mio_first)
1682352f7f91STakashi Iwai {
1683352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1684352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1685352f7f91STakashi Iwai 	int i, err, badness;
1686352f7f91STakashi Iwai 
1687352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1688352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1689352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1690352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1691352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1692352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1693352f7f91STakashi Iwai 	spec->multi_ios = 0;
1694352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1695cd5be3f9STakashi Iwai 
1696cd5be3f9STakashi Iwai 	/* clear path indices */
1697cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1698cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1699cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1700cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1701cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1702c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1703cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1704cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1705cd5be3f9STakashi Iwai 
1706352f7f91STakashi Iwai 	badness = 0;
1707352f7f91STakashi Iwai 
1708352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1709352f7f91STakashi Iwai 	if (fill_hardwired) {
1710352f7f91STakashi Iwai 		bool mapped;
1711352f7f91STakashi Iwai 		do {
1712352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1713352f7f91STakashi Iwai 					     cfg->line_out_pins,
1714196c1766STakashi Iwai 					     spec->private_dac_nids,
1715196c1766STakashi Iwai 					     spec->out_paths);
1716352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1717352f7f91STakashi Iwai 					      cfg->hp_pins,
1718196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1719196c1766STakashi Iwai 					      spec->hp_paths);
1720352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1721352f7f91STakashi Iwai 					      cfg->speaker_pins,
1722196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1723196c1766STakashi Iwai 					      spec->speaker_paths);
1724da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1725da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1726352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1727e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1728352f7f91STakashi Iwai 				if (!err)
1729352f7f91STakashi Iwai 					mapped = true;
1730352f7f91STakashi Iwai 			}
1731352f7f91STakashi Iwai 		} while (mapped);
1732352f7f91STakashi Iwai 	}
1733352f7f91STakashi Iwai 
1734352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1735196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
173698bd1115STakashi Iwai 				   spec->main_out_badness);
1737352f7f91STakashi Iwai 
1738da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1739352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1740352f7f91STakashi Iwai 		/* try to fill multi-io first */
1741e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1742352f7f91STakashi Iwai 		if (err < 0)
1743352f7f91STakashi Iwai 			return err;
1744352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1745352f7f91STakashi Iwai 	}
1746352f7f91STakashi Iwai 
1747352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1748352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1749352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1750196c1766STakashi Iwai 				      spec->hp_paths,
175198bd1115STakashi Iwai 				      spec->extra_out_badness);
1752352f7f91STakashi Iwai 		if (err < 0)
1753352f7f91STakashi Iwai 			return err;
1754352f7f91STakashi Iwai 		badness += err;
1755352f7f91STakashi Iwai 	}
1756352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1757352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1758352f7f91STakashi Iwai 				      cfg->speaker_pins,
1759352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1760196c1766STakashi Iwai 				      spec->speaker_paths,
176198bd1115STakashi Iwai 				      spec->extra_out_badness);
1762352f7f91STakashi Iwai 		if (err < 0)
1763352f7f91STakashi Iwai 			return err;
1764352f7f91STakashi Iwai 		badness += err;
1765352f7f91STakashi Iwai 	}
1766da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1767da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1768e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1769352f7f91STakashi Iwai 		if (err < 0)
1770352f7f91STakashi Iwai 			return err;
1771352f7f91STakashi Iwai 		badness += err;
1772352f7f91STakashi Iwai 	}
1773e22aab7dSTakashi Iwai 
1774c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1775c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1776c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1777c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1778c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1779c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1780c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1781c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1782c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1783c30aa7b2STakashi Iwai 	}
1784c30aa7b2STakashi Iwai 
1785da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1786da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1787e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1788e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1789352f7f91STakashi Iwai 
1790a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1791a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1792a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1793a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1794a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1795a07a949bSTakashi Iwai 		else {
1796a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1797a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1798a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1799a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1800a07a949bSTakashi Iwai 		}
1801a07a949bSTakashi Iwai 	}
1802a07a949bSTakashi Iwai 
1803a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1804c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1805a07a949bSTakashi Iwai 
1806352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1807352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1808352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1809352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1810352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1811352f7f91STakashi Iwai 		spec->multi_ios = 0;
1812352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1813352f7f91STakashi Iwai 	}
1814352f7f91STakashi Iwai 
181555a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
181655a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
181755a63d4dSTakashi Iwai 
1818a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1819a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1820a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1821a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1822a07a949bSTakashi Iwai 				   spec->hp_paths);
1823a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1824a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1825a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1826a07a949bSTakashi Iwai 				   spec->speaker_paths);
1827a07a949bSTakashi Iwai 
1828352f7f91STakashi Iwai 	return badness;
1829352f7f91STakashi Iwai }
1830352f7f91STakashi Iwai 
1831352f7f91STakashi Iwai #define DEBUG_BADNESS
1832352f7f91STakashi Iwai 
1833352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1834d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1835d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1836352f7f91STakashi Iwai #else
1837d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1838d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1839352f7f91STakashi Iwai #endif
1840352f7f91STakashi Iwai 
1841a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1842a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1843a769409cSTakashi Iwai 				      const char *pfx, int idx)
1844352f7f91STakashi Iwai {
1845a769409cSTakashi Iwai 	struct nid_path *path;
1846a769409cSTakashi Iwai 
1847a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1848a769409cSTakashi Iwai 	if (path)
18494e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1850a769409cSTakashi Iwai }
1851a769409cSTakashi Iwai 
1852a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1853a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1854a769409cSTakashi Iwai {
1855a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1856a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1857a769409cSTakashi Iwai 	int i;
1858a769409cSTakashi Iwai 
1859a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1860352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1861708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1862352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1863352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1864352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1865a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1866a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1867a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1868a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1869352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1870352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1871352f7f91STakashi Iwai 			      spec->multi_ios,
1872352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1873352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1874a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1875a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1876a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1877a769409cSTakashi Iwai 	if (cfg->hp_outs)
1878352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1879352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1880708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1881352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1882352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1883352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1884352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1885a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1886a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1887a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1888352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1889352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1890352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1891352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1892352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1893352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1894352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1895a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1896a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1897a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1898a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1899352f7f91STakashi Iwai }
1900a769409cSTakashi Iwai #else
1901a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1902a769409cSTakashi Iwai #endif
1903352f7f91STakashi Iwai 
1904352f7f91STakashi Iwai /* find all available DACs of the codec */
1905352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1906352f7f91STakashi Iwai {
1907352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
19087639a06cSTakashi Iwai 	hda_nid_t nid;
1909352f7f91STakashi Iwai 
1910352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1911352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
19127639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
1913352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1914352f7f91STakashi Iwai 			continue;
1915352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
19164e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1917352f7f91STakashi Iwai 			break;
1918352f7f91STakashi Iwai 		}
1919352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1920352f7f91STakashi Iwai 	}
1921352f7f91STakashi Iwai }
1922352f7f91STakashi Iwai 
1923352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1924352f7f91STakashi Iwai {
1925352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1926352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1927352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
19289314a581STakashi Iwai 	unsigned int val;
1929352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1930352f7f91STakashi Iwai 	int badness;
1931352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1932352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1933352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1934352f7f91STakashi Iwai 
1935352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1936352f7f91STakashi Iwai 	if (!best_cfg)
1937352f7f91STakashi Iwai 		return -ENOMEM;
1938352f7f91STakashi Iwai 	*best_cfg = *cfg;
1939352f7f91STakashi Iwai 
1940352f7f91STakashi Iwai 	for (;;) {
1941352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1942352f7f91STakashi Iwai 					     fill_mio_first);
1943352f7f91STakashi Iwai 		if (badness < 0) {
1944352f7f91STakashi Iwai 			kfree(best_cfg);
1945352f7f91STakashi Iwai 			return badness;
1946352f7f91STakashi Iwai 		}
1947352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1948352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1949352f7f91STakashi Iwai 			      badness);
1950a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1951352f7f91STakashi Iwai 		if (badness < best_badness) {
1952352f7f91STakashi Iwai 			best_badness = badness;
1953352f7f91STakashi Iwai 			*best_cfg = *cfg;
1954352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1955352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1956352f7f91STakashi Iwai 		}
1957352f7f91STakashi Iwai 		if (!badness)
1958352f7f91STakashi Iwai 			break;
1959352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1960352f7f91STakashi Iwai 		if (!fill_mio_first)
1961352f7f91STakashi Iwai 			continue;
1962352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1963352f7f91STakashi Iwai 		if (!fill_hardwired)
1964352f7f91STakashi Iwai 			continue;
1965352f7f91STakashi Iwai 		if (hp_spk_swapped)
1966352f7f91STakashi Iwai 			break;
1967352f7f91STakashi Iwai 		hp_spk_swapped = true;
1968352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1969352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1970352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1971352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1972352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1973352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1974352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1975352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1976352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1977352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1978352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1979352f7f91STakashi Iwai 			fill_hardwired = true;
1980352f7f91STakashi Iwai 			continue;
1981352f7f91STakashi Iwai 		}
1982352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1983352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1984352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1985352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1986352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1987352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1988352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1989352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1990352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1991352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1992352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1993352f7f91STakashi Iwai 			fill_hardwired = true;
1994352f7f91STakashi Iwai 			continue;
1995352f7f91STakashi Iwai 		}
1996352f7f91STakashi Iwai 		break;
1997352f7f91STakashi Iwai 	}
1998352f7f91STakashi Iwai 
1999352f7f91STakashi Iwai 	if (badness) {
20000c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
2001352f7f91STakashi Iwai 		*cfg = *best_cfg;
2002352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
2003352f7f91STakashi Iwai 	}
2004352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2005352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
2006a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
2007352f7f91STakashi Iwai 
2008352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
2009352f7f91STakashi Iwai 		struct nid_path *path;
2010196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2011352f7f91STakashi Iwai 		if (path)
2012352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2013d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
20147a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
20157a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
2016d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
2017d89c6c0cSTakashi Iwai 				spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
2018d89c6c0cSTakashi Iwai 		}
2019352f7f91STakashi Iwai 	}
2020352f7f91STakashi Iwai 
20219314a581STakashi Iwai 	/* set initial pinctl targets */
20229314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
20239314a581STakashi Iwai 		val = PIN_HP;
20249314a581STakashi Iwai 	else
20259314a581STakashi Iwai 		val = PIN_OUT;
20269314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
20279314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
20289314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
20299314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
20309314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
20319314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
20329314a581STakashi Iwai 				cfg->speaker_pins, val);
20339314a581STakashi Iwai 	}
20349314a581STakashi Iwai 
203555a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
203655a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
203755a63d4dSTakashi Iwai 		spec->indep_hp = 0;
203855a63d4dSTakashi Iwai 
2039352f7f91STakashi Iwai 	kfree(best_cfg);
2040352f7f91STakashi Iwai 	return 0;
2041352f7f91STakashi Iwai }
2042352f7f91STakashi Iwai 
2043352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
2044352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
2045352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
2046352f7f91STakashi Iwai {
2047352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2048352f7f91STakashi Iwai 	int i, err, noutputs;
2049352f7f91STakashi Iwai 
2050352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
2051352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2052352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
2053352f7f91STakashi Iwai 
2054352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
2055352f7f91STakashi Iwai 		const char *name;
2056352f7f91STakashi Iwai 		int index;
2057352f7f91STakashi Iwai 		struct nid_path *path;
2058352f7f91STakashi Iwai 
2059196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2060352f7f91STakashi Iwai 		if (!path)
2061352f7f91STakashi Iwai 			continue;
2062247d85eeSTakashi Iwai 
2063247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2064352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2065352f7f91STakashi Iwai 			/* Center/LFE */
2066352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2067352f7f91STakashi Iwai 			if (err < 0)
2068352f7f91STakashi Iwai 				return err;
2069352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2070352f7f91STakashi Iwai 			if (err < 0)
2071352f7f91STakashi Iwai 				return err;
2072247d85eeSTakashi Iwai 		} else {
2073247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2074247d85eeSTakashi Iwai 			if (err < 0)
2075247d85eeSTakashi Iwai 				return err;
2076247d85eeSTakashi Iwai 		}
2077247d85eeSTakashi Iwai 
2078247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2079247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2080352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2081352f7f91STakashi Iwai 			if (err < 0)
2082352f7f91STakashi Iwai 				return err;
2083352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2084352f7f91STakashi Iwai 			if (err < 0)
2085352f7f91STakashi Iwai 				return err;
2086352f7f91STakashi Iwai 		} else {
2087352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2088352f7f91STakashi Iwai 			if (err < 0)
2089352f7f91STakashi Iwai 				return err;
2090352f7f91STakashi Iwai 		}
2091352f7f91STakashi Iwai 	}
2092352f7f91STakashi Iwai 	return 0;
2093352f7f91STakashi Iwai }
2094352f7f91STakashi Iwai 
2095c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2096196c1766STakashi Iwai 			    const char *pfx, int cidx)
2097352f7f91STakashi Iwai {
2098352f7f91STakashi Iwai 	struct nid_path *path;
2099352f7f91STakashi Iwai 	int err;
2100352f7f91STakashi Iwai 
2101196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2102352f7f91STakashi Iwai 	if (!path)
2103352f7f91STakashi Iwai 		return 0;
2104352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2105352f7f91STakashi Iwai 	if (err < 0)
2106352f7f91STakashi Iwai 		return err;
2107352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2108352f7f91STakashi Iwai 	if (err < 0)
2109352f7f91STakashi Iwai 		return err;
2110352f7f91STakashi Iwai 	return 0;
2111352f7f91STakashi Iwai }
2112352f7f91STakashi Iwai 
2113352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2114352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2115196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2116352f7f91STakashi Iwai {
2117c2c80383STakashi Iwai 	int i;
2118352f7f91STakashi Iwai 
2119352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2120c2c80383STakashi Iwai 		const char *name;
2121975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2122c2c80383STakashi Iwai 		int err, idx = 0;
2123c2c80383STakashi Iwai 
2124c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2125c2c80383STakashi Iwai 			name = "Bass Speaker";
2126c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2127c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2128352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2129c2c80383STakashi Iwai 			name = tmp;
2130352f7f91STakashi Iwai 		} else {
2131c2c80383STakashi Iwai 			name = pfx;
2132c2c80383STakashi Iwai 			idx = i;
2133352f7f91STakashi Iwai 		}
2134c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2135352f7f91STakashi Iwai 		if (err < 0)
2136352f7f91STakashi Iwai 			return err;
2137352f7f91STakashi Iwai 	}
2138352f7f91STakashi Iwai 	return 0;
2139352f7f91STakashi Iwai }
2140352f7f91STakashi Iwai 
2141352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2142352f7f91STakashi Iwai {
2143352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2144352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2145196c1766STakashi Iwai 				 spec->hp_paths,
2146352f7f91STakashi Iwai 				 "Headphone");
2147352f7f91STakashi Iwai }
2148352f7f91STakashi Iwai 
2149352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2150352f7f91STakashi Iwai {
2151352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2152352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2153196c1766STakashi Iwai 				 spec->speaker_paths,
2154352f7f91STakashi Iwai 				 "Speaker");
2155352f7f91STakashi Iwai }
2156352f7f91STakashi Iwai 
2157352f7f91STakashi Iwai /*
215838cf6f1aSTakashi Iwai  * independent HP controls
215938cf6f1aSTakashi Iwai  */
216038cf6f1aSTakashi Iwai 
21611a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
21621a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
216338cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
216438cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
216538cf6f1aSTakashi Iwai {
216638cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
216738cf6f1aSTakashi Iwai }
216838cf6f1aSTakashi Iwai 
216938cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
217038cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
217138cf6f1aSTakashi Iwai {
217238cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
217338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
217438cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
217538cf6f1aSTakashi Iwai 	return 0;
217638cf6f1aSTakashi Iwai }
217738cf6f1aSTakashi Iwai 
2178a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2179a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2180a1e908edSTakashi Iwai 			       int out_type);
2181a1e908edSTakashi Iwai 
218238cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
218338cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
218438cf6f1aSTakashi Iwai {
218538cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
218638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
218738cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
218838cf6f1aSTakashi Iwai 	int ret = 0;
218938cf6f1aSTakashi Iwai 
219038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
219138cf6f1aSTakashi Iwai 	if (spec->active_streams) {
219238cf6f1aSTakashi Iwai 		ret = -EBUSY;
219338cf6f1aSTakashi Iwai 		goto unlock;
219438cf6f1aSTakashi Iwai 	}
219538cf6f1aSTakashi Iwai 
219638cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2197a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2198a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2199a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2200a1e908edSTakashi Iwai 		else
2201a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2202a1e908edSTakashi Iwai 
2203a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2204a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2205a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2206a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2207a1e908edSTakashi Iwai 						   spec->out_paths[0],
2208a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2209a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2210a1e908edSTakashi Iwai 			else
2211a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2212a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2213a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2214a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2215a1e908edSTakashi Iwai 		}
2216a1e908edSTakashi Iwai 
221738cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
221838cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2219a1e908edSTakashi Iwai 			*dacp = 0;
222038cf6f1aSTakashi Iwai 		else
2221a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
222292603c59STakashi Iwai 
2223963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
222438cf6f1aSTakashi Iwai 		ret = 1;
222538cf6f1aSTakashi Iwai 	}
222638cf6f1aSTakashi Iwai  unlock:
222738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
222838cf6f1aSTakashi Iwai 	return ret;
222938cf6f1aSTakashi Iwai }
223038cf6f1aSTakashi Iwai 
223138cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
223238cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
223338cf6f1aSTakashi Iwai 	.name = "Independent HP",
223438cf6f1aSTakashi Iwai 	.info = indep_hp_info,
223538cf6f1aSTakashi Iwai 	.get = indep_hp_get,
223638cf6f1aSTakashi Iwai 	.put = indep_hp_put,
223738cf6f1aSTakashi Iwai };
223838cf6f1aSTakashi Iwai 
223938cf6f1aSTakashi Iwai 
224038cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
224138cf6f1aSTakashi Iwai {
224238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2243a1e908edSTakashi Iwai 	hda_nid_t dac;
224438cf6f1aSTakashi Iwai 
224538cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
224638cf6f1aSTakashi Iwai 		return 0;
2247a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2248a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2249a1e908edSTakashi Iwai 	else
2250a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2251a1e908edSTakashi Iwai 	if (!dac) {
225238cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
225338cf6f1aSTakashi Iwai 		return 0;
225438cf6f1aSTakashi Iwai 	}
225538cf6f1aSTakashi Iwai 
225638cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2257a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
225838cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
225938cf6f1aSTakashi Iwai 		return -ENOMEM;
226038cf6f1aSTakashi Iwai 	return 0;
226138cf6f1aSTakashi Iwai }
226238cf6f1aSTakashi Iwai 
226338cf6f1aSTakashi Iwai /*
2264352f7f91STakashi Iwai  * channel mode enum control
2265352f7f91STakashi Iwai  */
2266352f7f91STakashi Iwai 
2267352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2268352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2269352f7f91STakashi Iwai {
2270352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2271352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2272a07a949bSTakashi Iwai 	int chs;
2273352f7f91STakashi Iwai 
2274352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2275352f7f91STakashi Iwai 	uinfo->count = 1;
2276352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2277352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2278352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2279a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2280a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2281352f7f91STakashi Iwai 	return 0;
2282352f7f91STakashi Iwai }
2283352f7f91STakashi Iwai 
2284352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2285352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2286352f7f91STakashi Iwai {
2287352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2288352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2289a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2290a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2291352f7f91STakashi Iwai 	return 0;
2292352f7f91STakashi Iwai }
2293352f7f91STakashi Iwai 
2294196c1766STakashi Iwai static inline struct nid_path *
2295196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2296196c1766STakashi Iwai {
2297196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2298196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2299196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2300196c1766STakashi Iwai }
2301196c1766STakashi Iwai 
2302a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2303a5cc2509STakashi Iwai 
230465033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
230565033cc8STakashi Iwai  * used for output paths
230665033cc8STakashi Iwai  */
230765033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
230865033cc8STakashi Iwai {
230965033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
231065033cc8STakashi Iwai }
231165033cc8STakashi Iwai 
2312352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2313352f7f91STakashi Iwai {
2314352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2315352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2316352f7f91STakashi Iwai 	struct nid_path *path;
2317352f7f91STakashi Iwai 
2318196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2319352f7f91STakashi Iwai 	if (!path)
2320352f7f91STakashi Iwai 		return -EINVAL;
2321352f7f91STakashi Iwai 
2322352f7f91STakashi Iwai 	if (path->active == output)
2323352f7f91STakashi Iwai 		return 0;
2324352f7f91STakashi Iwai 
2325352f7f91STakashi Iwai 	if (output) {
23262c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
232765033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2328d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2329352f7f91STakashi Iwai 	} else {
2330d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
233165033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
23322c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
233355196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2334352f7f91STakashi Iwai 	}
2335a365fed9STakashi Iwai 
2336a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2337a5cc2509STakashi Iwai 	update_automute_all(codec);
2338a365fed9STakashi Iwai 
2339352f7f91STakashi Iwai 	return 0;
2340352f7f91STakashi Iwai }
2341352f7f91STakashi Iwai 
2342352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2343352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2344352f7f91STakashi Iwai {
2345352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2346352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2347352f7f91STakashi Iwai 	int i, ch;
2348352f7f91STakashi Iwai 
2349352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2350352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2351352f7f91STakashi Iwai 		return -EINVAL;
2352a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2353352f7f91STakashi Iwai 		return 0;
2354a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2355352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2356352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2357352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2358352f7f91STakashi Iwai 					  spec->const_channel_count);
2359352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2360352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2361352f7f91STakashi Iwai 	return 1;
2362352f7f91STakashi Iwai }
2363352f7f91STakashi Iwai 
2364352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2365352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2366352f7f91STakashi Iwai 	.name = "Channel Mode",
2367352f7f91STakashi Iwai 	.info = ch_mode_info,
2368352f7f91STakashi Iwai 	.get = ch_mode_get,
2369352f7f91STakashi Iwai 	.put = ch_mode_put,
2370352f7f91STakashi Iwai };
2371352f7f91STakashi Iwai 
2372352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2373352f7f91STakashi Iwai {
2374352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2375352f7f91STakashi Iwai 
2376352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
237712c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2378352f7f91STakashi Iwai 			return -ENOMEM;
2379352f7f91STakashi Iwai 	}
2380352f7f91STakashi Iwai 	return 0;
2381352f7f91STakashi Iwai }
2382352f7f91STakashi Iwai 
2383352f7f91STakashi Iwai /*
2384c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2385c30aa7b2STakashi Iwai  */
2386c30aa7b2STakashi Iwai 
2387c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2388c30aa7b2STakashi Iwai 
2389c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2390c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2391c30aa7b2STakashi Iwai {
2392c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2393c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2394c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2395c30aa7b2STakashi Iwai 	return 0;
2396c30aa7b2STakashi Iwai }
2397c30aa7b2STakashi Iwai 
2398c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2399a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2400a1e908edSTakashi Iwai 			       int out_type)
2401c30aa7b2STakashi Iwai {
2402a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2403c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2404c30aa7b2STakashi Iwai 
2405c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2406c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2407c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2408c30aa7b2STakashi Iwai 		return;
2409a1e908edSTakashi Iwai 
2410a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2411a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2412a1e908edSTakashi Iwai 	 */
2413a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2414a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2415a1e908edSTakashi Iwai 		do_mix = false;
2416a1e908edSTakashi Iwai 
2417c30aa7b2STakashi Iwai 	if (do_mix) {
2418c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2419c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
242055196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2421c30aa7b2STakashi Iwai 	} else {
242265033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
242365033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
242455196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2425c30aa7b2STakashi Iwai 	}
2426c30aa7b2STakashi Iwai }
2427c30aa7b2STakashi Iwai 
2428e7fdd527STakashi Iwai /* re-initialize the output paths; only called from loopback_mixing_put() */
2429e7fdd527STakashi Iwai static void update_output_paths(struct hda_codec *codec, int num_outs,
2430e7fdd527STakashi Iwai 				const int *paths)
2431e7fdd527STakashi Iwai {
2432e7fdd527STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2433e7fdd527STakashi Iwai 	struct nid_path *path;
2434e7fdd527STakashi Iwai 	int i;
2435e7fdd527STakashi Iwai 
2436e7fdd527STakashi Iwai 	for (i = 0; i < num_outs; i++) {
2437e7fdd527STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2438e7fdd527STakashi Iwai 		if (path)
2439e7fdd527STakashi Iwai 			snd_hda_activate_path(codec, path, path->active,
2440e7fdd527STakashi Iwai 					      spec->aamix_mode);
2441e7fdd527STakashi Iwai 	}
2442e7fdd527STakashi Iwai }
2443e7fdd527STakashi Iwai 
2444c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2445c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2446c30aa7b2STakashi Iwai {
2447c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2448c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2449e7fdd527STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2450c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2451c30aa7b2STakashi Iwai 
2452c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2453c30aa7b2STakashi Iwai 		return 0;
2454c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2455e7fdd527STakashi Iwai 	if (has_aamix_out_paths(spec)) {
2456c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->out_paths[0],
2457a1e908edSTakashi Iwai 				   spec->aamix_out_paths[0],
2458e7fdd527STakashi Iwai 				   cfg->line_out_type);
2459c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->hp_paths[0],
2460a1e908edSTakashi Iwai 				   spec->aamix_out_paths[1],
2461a1e908edSTakashi Iwai 				   AUTO_PIN_HP_OUT);
2462c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2463a1e908edSTakashi Iwai 				   spec->aamix_out_paths[2],
2464a1e908edSTakashi Iwai 				   AUTO_PIN_SPEAKER_OUT);
2465e7fdd527STakashi Iwai 	} else {
2466e7fdd527STakashi Iwai 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2467e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2468e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2469e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2470e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->speaker_outs,
2471e7fdd527STakashi Iwai 					    spec->speaker_paths);
2472e7fdd527STakashi Iwai 	}
2473c30aa7b2STakashi Iwai 	return 1;
2474c30aa7b2STakashi Iwai }
2475c30aa7b2STakashi Iwai 
2476c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2477c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2478c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2479c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2480c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2481c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2482c30aa7b2STakashi Iwai };
2483c30aa7b2STakashi Iwai 
2484c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2485c30aa7b2STakashi Iwai {
2486c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2487c30aa7b2STakashi Iwai 
2488c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2489c30aa7b2STakashi Iwai 		return 0;
2490c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2491c30aa7b2STakashi Iwai 		return -ENOMEM;
2492a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2493e7fdd527STakashi Iwai 	/* if no explicit aamix path is present (e.g. for Realtek codecs),
2494e7fdd527STakashi Iwai 	 * enable aamix as default -- just for compatibility
2495e7fdd527STakashi Iwai 	 */
2496e7fdd527STakashi Iwai 	spec->aamix_mode = !has_aamix_out_paths(spec);
2497c30aa7b2STakashi Iwai 	return 0;
2498c30aa7b2STakashi Iwai }
2499c30aa7b2STakashi Iwai 
2500c30aa7b2STakashi Iwai /*
2501352f7f91STakashi Iwai  * shared headphone/mic handling
2502352f7f91STakashi Iwai  */
2503352f7f91STakashi Iwai 
2504352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2505352f7f91STakashi Iwai 
2506352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2507967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2508352f7f91STakashi Iwai {
2509352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2510967303daSTakashi Iwai 	bool as_mic;
2511352f7f91STakashi Iwai 	unsigned int val;
2512967303daSTakashi Iwai 	hda_nid_t pin;
2513967303daSTakashi Iwai 
2514967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2515967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2516967303daSTakashi Iwai 
2517967303daSTakashi Iwai 	if (!force) {
2518967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2519967303daSTakashi Iwai 		if (as_mic) {
2520967303daSTakashi Iwai 			if (val & PIN_IN)
2521967303daSTakashi Iwai 				return;
2522967303daSTakashi Iwai 		} else {
2523967303daSTakashi Iwai 			if (val & PIN_OUT)
2524967303daSTakashi Iwai 				return;
2525967303daSTakashi Iwai 		}
2526967303daSTakashi Iwai 	}
2527352f7f91STakashi Iwai 
2528352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2529967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2530967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2531967303daSTakashi Iwai 	 */
2532352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2533352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2534352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2535352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
25367594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2537967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2538352f7f91STakashi Iwai 	}
2539352f7f91STakashi Iwai 
25408ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2541967303daSTakashi Iwai 		if (as_mic)
2542967303daSTakashi Iwai 			val |= PIN_IN;
2543967303daSTakashi Iwai 		else
2544967303daSTakashi Iwai 			val = PIN_HP;
25452c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2546963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
25478ba955ceSTakashi Iwai 	}
2548352f7f91STakashi Iwai }
2549352f7f91STakashi Iwai 
2550352f7f91STakashi Iwai /* create a shared input with the headphone out */
2551967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2552352f7f91STakashi Iwai {
2553352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2554352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2555352f7f91STakashi Iwai 	unsigned int defcfg;
2556352f7f91STakashi Iwai 	hda_nid_t nid;
2557352f7f91STakashi Iwai 
2558967303daSTakashi Iwai 	if (!spec->hp_mic) {
2559967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2560352f7f91STakashi Iwai 			return 0;
2561967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2562967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2563967303daSTakashi Iwai 		 */
2564967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2565967303daSTakashi Iwai 			return 0;
2566967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2567352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2568352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2569352f7f91STakashi Iwai 				return 0;
2570967303daSTakashi Iwai 		}
2571967303daSTakashi Iwai 	}
2572352f7f91STakashi Iwai 
2573967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2574967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2575967303daSTakashi Iwai 		return 0;
2576967303daSTakashi Iwai 
2577967303daSTakashi Iwai 	nid = 0;
2578967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2579967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2580967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2581967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2582967303daSTakashi Iwai 	if (!nid)
2583967303daSTakashi Iwai 		return 0;
2584352f7f91STakashi Iwai 
2585352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2586352f7f91STakashi Iwai 		return 0; /* no input */
2587352f7f91STakashi Iwai 
2588967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2589967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2590cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2591967303daSTakashi Iwai 	cfg->num_inputs++;
2592967303daSTakashi Iwai 	spec->hp_mic = 1;
2593967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2594967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2595967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
25964e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2597352f7f91STakashi Iwai 	return 0;
2598352f7f91STakashi Iwai }
2599352f7f91STakashi Iwai 
2600978e77e7STakashi Iwai /*
2601978e77e7STakashi Iwai  * output jack mode
2602978e77e7STakashi Iwai  */
26035f171baaSTakashi Iwai 
26045f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
26055f171baaSTakashi Iwai 
26065f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
26075f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
26085f171baaSTakashi Iwai };
26095f171baaSTakashi Iwai 
2610978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2611978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2612978e77e7STakashi Iwai {
26135f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2614978e77e7STakashi Iwai }
2615978e77e7STakashi Iwai 
2616978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2617978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2618978e77e7STakashi Iwai {
2619978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2620978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2621978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2622978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2623978e77e7STakashi Iwai 	else
2624978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2625978e77e7STakashi Iwai 	return 0;
2626978e77e7STakashi Iwai }
2627978e77e7STakashi Iwai 
2628978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2629978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2630978e77e7STakashi Iwai {
2631978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2632978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2633978e77e7STakashi Iwai 	unsigned int val;
2634978e77e7STakashi Iwai 
2635978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2636978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2637978e77e7STakashi Iwai 		return 0;
2638978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2639978e77e7STakashi Iwai 	return 1;
2640978e77e7STakashi Iwai }
2641978e77e7STakashi Iwai 
2642978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2643978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2644978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2645978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2646978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2647978e77e7STakashi Iwai };
2648978e77e7STakashi Iwai 
2649978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2650978e77e7STakashi Iwai {
2651978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2652978e77e7STakashi Iwai 	int i;
2653978e77e7STakashi Iwai 
2654978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2655978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2656978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2657978e77e7STakashi Iwai 			return true;
2658978e77e7STakashi Iwai 	}
2659978e77e7STakashi Iwai 	return false;
2660978e77e7STakashi Iwai }
2661978e77e7STakashi Iwai 
2662978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2663978e77e7STakashi Iwai 			       char *name, size_t name_len)
2664978e77e7STakashi Iwai {
2665978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2666978e77e7STakashi Iwai 	int idx = 0;
2667978e77e7STakashi Iwai 
2668978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2669978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2670978e77e7STakashi Iwai 
2671978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2672978e77e7STakashi Iwai 		;
2673978e77e7STakashi Iwai }
2674978e77e7STakashi Iwai 
26755f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26765f171baaSTakashi Iwai {
26775f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2678f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
26795f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
26805f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
26815f171baaSTakashi Iwai 			return 2;
26825f171baaSTakashi Iwai 	}
26835f171baaSTakashi Iwai 	return 1;
26845f171baaSTakashi Iwai }
26855f171baaSTakashi Iwai 
2686978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2687978e77e7STakashi Iwai 				 hda_nid_t *pins)
2688978e77e7STakashi Iwai {
2689978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2690978e77e7STakashi Iwai 	int i;
2691978e77e7STakashi Iwai 
2692978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2693978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2694ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
26955f171baaSTakashi Iwai 			continue;
26965f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2697978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2698975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2699978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2700978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2701978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2702978e77e7STakashi Iwai 			if (!knew)
2703978e77e7STakashi Iwai 				return -ENOMEM;
2704978e77e7STakashi Iwai 			knew->private_value = pin;
2705978e77e7STakashi Iwai 		}
2706978e77e7STakashi Iwai 	}
2707978e77e7STakashi Iwai 
2708978e77e7STakashi Iwai 	return 0;
2709978e77e7STakashi Iwai }
2710978e77e7STakashi Iwai 
271129476558STakashi Iwai /*
271229476558STakashi Iwai  * input jack mode
271329476558STakashi Iwai  */
271429476558STakashi Iwai 
271529476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
271629476558STakashi Iwai #define NUM_VREFS	6
271729476558STakashi Iwai 
271829476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
271929476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
272029476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
272129476558STakashi Iwai };
272229476558STakashi Iwai 
272329476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
272429476558STakashi Iwai {
272529476558STakashi Iwai 	unsigned int pincap;
272629476558STakashi Iwai 
272729476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
272829476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
272929476558STakashi Iwai 	/* filter out unusual vrefs */
273029476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
273129476558STakashi Iwai 	return pincap;
273229476558STakashi Iwai }
273329476558STakashi Iwai 
273429476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
273529476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
273629476558STakashi Iwai {
273729476558STakashi Iwai 	unsigned int i, n = 0;
273829476558STakashi Iwai 
273929476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
274029476558STakashi Iwai 		if (vref_caps & (1 << i)) {
274129476558STakashi Iwai 			if (n == item_idx)
274229476558STakashi Iwai 				return i;
274329476558STakashi Iwai 			n++;
274429476558STakashi Iwai 		}
274529476558STakashi Iwai 	}
274629476558STakashi Iwai 	return 0;
274729476558STakashi Iwai }
274829476558STakashi Iwai 
274929476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
275029476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
275129476558STakashi Iwai {
275229476558STakashi Iwai 	unsigned int i, n = 0;
275329476558STakashi Iwai 
275429476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
275529476558STakashi Iwai 		if (i == idx)
275629476558STakashi Iwai 			return n;
275729476558STakashi Iwai 		if (vref_caps & (1 << i))
275829476558STakashi Iwai 			n++;
275929476558STakashi Iwai 	}
276029476558STakashi Iwai 	return 0;
276129476558STakashi Iwai }
276229476558STakashi Iwai 
276329476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
276429476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
276529476558STakashi Iwai {
276629476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
276729476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
276829476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
276929476558STakashi Iwai 
277029476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
277129476558STakashi Iwai 				 vref_texts);
277229476558STakashi Iwai 	/* set the right text */
277329476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
277429476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
277529476558STakashi Iwai 	return 0;
277629476558STakashi Iwai }
277729476558STakashi Iwai 
277829476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
277929476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
278029476558STakashi Iwai {
278129476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
278229476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
278329476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
278429476558STakashi Iwai 	unsigned int idx;
278529476558STakashi Iwai 
278629476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
278729476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
278829476558STakashi Iwai 	return 0;
278929476558STakashi Iwai }
279029476558STakashi Iwai 
279129476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
279229476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
279329476558STakashi Iwai {
279429476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
279529476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
279629476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
279729476558STakashi Iwai 	unsigned int val, idx;
279829476558STakashi Iwai 
279929476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
280029476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
280129476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
280229476558STakashi Iwai 		return 0;
280329476558STakashi Iwai 
280429476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
280529476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
280629476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
280729476558STakashi Iwai 	return 1;
280829476558STakashi Iwai }
280929476558STakashi Iwai 
281029476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
281129476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
281229476558STakashi Iwai 	.info = in_jack_mode_info,
281329476558STakashi Iwai 	.get = in_jack_mode_get,
281429476558STakashi Iwai 	.put = in_jack_mode_put,
281529476558STakashi Iwai };
281629476558STakashi Iwai 
28175f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
28185f171baaSTakashi Iwai {
28195f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28205f171baaSTakashi Iwai 	int nitems = 0;
2821f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
28225f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
28235f171baaSTakashi Iwai 	return nitems ? nitems : 1;
28245f171baaSTakashi Iwai }
28255f171baaSTakashi Iwai 
282629476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
282729476558STakashi Iwai {
282829476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
282929476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2830975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
28315f171baaSTakashi Iwai 	unsigned int defcfg;
28325f171baaSTakashi Iwai 
2833f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2834f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
283529476558STakashi Iwai 
283629476558STakashi Iwai 	/* no jack mode for fixed pins */
283729476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
283829476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
283929476558STakashi Iwai 		return 0;
284029476558STakashi Iwai 
284129476558STakashi Iwai 	/* no multiple vref caps? */
28425f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
284329476558STakashi Iwai 		return 0;
284429476558STakashi Iwai 
284529476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
284629476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
284729476558STakashi Iwai 	if (!knew)
284829476558STakashi Iwai 		return -ENOMEM;
284929476558STakashi Iwai 	knew->private_value = pin;
285029476558STakashi Iwai 	return 0;
285129476558STakashi Iwai }
285229476558STakashi Iwai 
28535f171baaSTakashi Iwai /*
28545f171baaSTakashi Iwai  * HP/mic shared jack mode
28555f171baaSTakashi Iwai  */
28565f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
28575f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
28585f171baaSTakashi Iwai {
28595f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28605f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
28615f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
28625f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
28635f171baaSTakashi Iwai 	const char *text = NULL;
28645f171baaSTakashi Iwai 	int idx;
28655f171baaSTakashi Iwai 
28665f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
28675f171baaSTakashi Iwai 	uinfo->count = 1;
28685f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
28695f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
28705f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
28715f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
28725f171baaSTakashi Iwai 	if (idx < out_jacks) {
28735f171baaSTakashi Iwai 		if (out_jacks > 1)
28745f171baaSTakashi Iwai 			text = out_jack_texts[idx];
28755f171baaSTakashi Iwai 		else
28765f171baaSTakashi Iwai 			text = "Headphone Out";
28775f171baaSTakashi Iwai 	} else {
28785f171baaSTakashi Iwai 		idx -= out_jacks;
28795f171baaSTakashi Iwai 		if (in_jacks > 1) {
28805f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
28815f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
28825f171baaSTakashi Iwai 		} else
28835f171baaSTakashi Iwai 			text = "Mic In";
28845f171baaSTakashi Iwai 	}
28855f171baaSTakashi Iwai 
28865f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
28875f171baaSTakashi Iwai 	return 0;
28885f171baaSTakashi Iwai }
28895f171baaSTakashi Iwai 
28905f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
28915f171baaSTakashi Iwai {
28925f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
28935f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
28945f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
28955f171baaSTakashi Iwai 	int idx = 0;
28965f171baaSTakashi Iwai 
28975f171baaSTakashi Iwai 	if (val & PIN_OUT) {
28985f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
28995f171baaSTakashi Iwai 			idx = 1;
29005f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
29015f171baaSTakashi Iwai 		idx = out_jacks;
29025f171baaSTakashi Iwai 		if (in_jacks > 1) {
29035f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29045f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
29055f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
29065f171baaSTakashi Iwai 		}
29075f171baaSTakashi Iwai 	}
29085f171baaSTakashi Iwai 	return idx;
29095f171baaSTakashi Iwai }
29105f171baaSTakashi Iwai 
29115f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
29125f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29135f171baaSTakashi Iwai {
29145f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29155f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29165f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
29175f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
29185f171baaSTakashi Iwai 	return 0;
29195f171baaSTakashi Iwai }
29205f171baaSTakashi Iwai 
29215f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
29225f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29235f171baaSTakashi Iwai {
29245f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29255f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29265f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29275f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29285f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
29295f171baaSTakashi Iwai 
29305f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
29315f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
29325f171baaSTakashi Iwai 	if (oldval == idx)
29335f171baaSTakashi Iwai 		return 0;
29345f171baaSTakashi Iwai 
29355f171baaSTakashi Iwai 	if (idx < out_jacks) {
29365f171baaSTakashi Iwai 		if (out_jacks > 1)
29375f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
29385f171baaSTakashi Iwai 		else
29395f171baaSTakashi Iwai 			val = PIN_HP;
29405f171baaSTakashi Iwai 	} else {
29415f171baaSTakashi Iwai 		idx -= out_jacks;
29425f171baaSTakashi Iwai 		if (in_jacks > 1) {
29435f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29445f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
29453f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
29463f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
29475f171baaSTakashi Iwai 		} else
294816c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
29495f171baaSTakashi Iwai 	}
29505f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2951963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
29528ba955ceSTakashi Iwai 
29535f171baaSTakashi Iwai 	return 1;
29545f171baaSTakashi Iwai }
29555f171baaSTakashi Iwai 
29565f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
29575f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
29585f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
29595f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
29605f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
29615f171baaSTakashi Iwai };
29625f171baaSTakashi Iwai 
29635f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
29645f171baaSTakashi Iwai {
29655f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
29665f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
29675f171baaSTakashi Iwai 
29685f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
29695f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
29705f171baaSTakashi Iwai 	if (!knew)
29715f171baaSTakashi Iwai 		return -ENOMEM;
29725f171baaSTakashi Iwai 	knew->private_value = pin;
29738ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
29745f171baaSTakashi Iwai 	return 0;
29755f171baaSTakashi Iwai }
2976352f7f91STakashi Iwai 
2977352f7f91STakashi Iwai /*
2978352f7f91STakashi Iwai  * Parse input paths
2979352f7f91STakashi Iwai  */
2980352f7f91STakashi Iwai 
2981352f7f91STakashi Iwai /* add the powersave loopback-list entry */
29820186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2983352f7f91STakashi Iwai {
2984352f7f91STakashi Iwai 	struct hda_amp_list *list;
2985352f7f91STakashi Iwai 
29860186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
29870186f4f4STakashi Iwai 	if (!list)
29880186f4f4STakashi Iwai 		return -ENOMEM;
2989352f7f91STakashi Iwai 	list->nid = mix;
2990352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2991352f7f91STakashi Iwai 	list->idx = idx;
29920186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
29930186f4f4STakashi Iwai 	return 0;
2994cb53c626STakashi Iwai }
2995cb53c626STakashi Iwai 
29962ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
29972ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
29982ded3e5bSTakashi Iwai  */
29992ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
30002ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
30012ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
30022ded3e5bSTakashi Iwai {
30032ded3e5bSTakashi Iwai 	int idx, num_conns;
30042ded3e5bSTakashi Iwai 	const hda_nid_t *list;
30052ded3e5bSTakashi Iwai 	hda_nid_t nid;
30062ded3e5bSTakashi Iwai 
30072ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
30082ded3e5bSTakashi Iwai 	if (idx < 0)
30092ded3e5bSTakashi Iwai 		return false;
30102ded3e5bSTakashi Iwai 
30112ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
30122ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
30132ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30142ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
30152ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30162ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
30172ded3e5bSTakashi Iwai 		return true;
30182ded3e5bSTakashi Iwai 
30192ded3e5bSTakashi Iwai 	/* check leaf node */
30202ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
30212ded3e5bSTakashi Iwai 	if (num_conns < idx)
30222ded3e5bSTakashi Iwai 		return false;
30232ded3e5bSTakashi Iwai 	nid = list[idx];
302443a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
302543a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
30262ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
302743a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
302843a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
30292ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
30302ded3e5bSTakashi Iwai 
30312ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
30322ded3e5bSTakashi Iwai }
30332ded3e5bSTakashi Iwai 
3034352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
3035196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
3036196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3037352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
30381da177e4SLinus Torvalds {
3039352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3040352f7f91STakashi Iwai 	struct nid_path *path;
30412ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
3042352f7f91STakashi Iwai 	int err, idx;
30431da177e4SLinus Torvalds 
30442ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
30452ded3e5bSTakashi Iwai 		return 0;
3046352f7f91STakashi Iwai 
30473ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3048352f7f91STakashi Iwai 	if (!path)
3049352f7f91STakashi Iwai 		return -EINVAL;
30504e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
3051196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3052352f7f91STakashi Iwai 
3053352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
30542ded3e5bSTakashi Iwai 	if (mix_val) {
30552ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3056d13bd412STakashi Iwai 		if (err < 0)
30571da177e4SLinus Torvalds 			return err;
30582ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
30591da177e4SLinus Torvalds 	}
30601da177e4SLinus Torvalds 
30612ded3e5bSTakashi Iwai 	if (mute_val) {
30622ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3063d13bd412STakashi Iwai 		if (err < 0)
30641da177e4SLinus Torvalds 			return err;
30652ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
30661da177e4SLinus Torvalds 	}
30671da177e4SLinus Torvalds 
3068352f7f91STakashi Iwai 	path->active = true;
3069e6feb5d0STakashi Iwai 	path->stream_enabled = true; /* no DAC/ADC involved */
30700186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
30710186f4f4STakashi Iwai 	if (err < 0)
30720186f4f4STakashi Iwai 		return err;
3073e4a395e7STakashi Iwai 
3074e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3075e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
3076e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3077e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
3078e4a395e7STakashi Iwai 		if (path) {
30794e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
3080e4a395e7STakashi Iwai 			path->active = true;
30816b275b14STakashi Iwai 			path->pin_fixed = true; /* static route */
3082e6feb5d0STakashi Iwai 			path->stream_enabled = true; /* no DAC/ADC involved */
3083e4a395e7STakashi Iwai 			spec->loopback_merge_path =
3084e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
3085e4a395e7STakashi Iwai 		}
3086e4a395e7STakashi Iwai 	}
3087e4a395e7STakashi Iwai 
3088352f7f91STakashi Iwai 	return 0;
30891da177e4SLinus Torvalds }
30901da177e4SLinus Torvalds 
3091352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
30921da177e4SLinus Torvalds {
3093352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3094352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
3095352f7f91STakashi Iwai }
3096352f7f91STakashi Iwai 
3097352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
3098352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
3099352f7f91STakashi Iwai {
3100352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3101352f7f91STakashi Iwai 	hda_nid_t nid;
3102352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
3103352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
31047639a06cSTakashi Iwai 	int nums = 0;
3105352f7f91STakashi Iwai 
31067639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
3107352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3108352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3109352f7f91STakashi Iwai 
3110352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3111352f7f91STakashi Iwai 			continue;
3112352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3113352f7f91STakashi Iwai 		if (++nums >= max_nums)
3114352f7f91STakashi Iwai 			break;
3115352f7f91STakashi Iwai 	}
3116352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
31170ffd534eSTakashi Iwai 
31180ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
31190ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
31200ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
31210ffd534eSTakashi Iwai 
3122352f7f91STakashi Iwai 	return nums;
3123352f7f91STakashi Iwai }
3124352f7f91STakashi Iwai 
3125352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3126352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3127352f7f91STakashi Iwai  */
3128352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3129352f7f91STakashi Iwai {
3130352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3131352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
31323a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3133352f7f91STakashi Iwai 	int i, n, nums;
3134352f7f91STakashi Iwai 
3135352f7f91STakashi Iwai 	nums = 0;
31363a65bcdcSTakashi Iwai 	ok_bits = 0;
3137352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3138352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
31393a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3140352f7f91STakashi Iwai 				break;
3141352f7f91STakashi Iwai 		}
31423a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
31433a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
31443a65bcdcSTakashi Iwai 			nums++;
31453a65bcdcSTakashi Iwai 		}
3146352f7f91STakashi Iwai 	}
3147352f7f91STakashi Iwai 
31483a65bcdcSTakashi Iwai 	if (!ok_bits) {
3149352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3150352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3151352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
31523a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3153352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3154352f7f91STakashi Iwai 					break;
3155352f7f91STakashi Iwai 				}
3156352f7f91STakashi Iwai 			}
3157352f7f91STakashi Iwai 		}
3158352f7f91STakashi Iwai 
31594e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3160352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3161352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
31623a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
31633a65bcdcSTakashi Iwai 		nums = 0;
31643a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
31653a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
31663a65bcdcSTakashi Iwai 				continue;
31673a65bcdcSTakashi Iwai 			if (n != nums) {
31683a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3169980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3170980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3171980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
31723a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
31733a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
31743a65bcdcSTakashi Iwai 				}
3175980428ceSTakashi Iwai 			}
31763a65bcdcSTakashi Iwai 			nums++;
31773a65bcdcSTakashi Iwai 		}
3178352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3179352f7f91STakashi Iwai 	}
3180352f7f91STakashi Iwai 
3181967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3182967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
31834e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3184352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3185352f7f91STakashi Iwai 	}
3186352f7f91STakashi Iwai 
3187352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3188352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3189352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3190352f7f91STakashi Iwai 
31911da177e4SLinus Torvalds 	return 0;
31921da177e4SLinus Torvalds }
31931da177e4SLinus Torvalds 
3194f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3195f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
31969dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
31979dba205bSTakashi Iwai 				const char *label, int anchor)
3198f3fc0b0bSTakashi Iwai {
3199f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3200f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3201f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3202f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3203f3fc0b0bSTakashi Iwai 	int c;
3204f3fc0b0bSTakashi Iwai 
3205f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3206f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3207f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3208f3fc0b0bSTakashi Iwai 
3209f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3210f3fc0b0bSTakashi Iwai 			continue;
3211f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3212f3fc0b0bSTakashi Iwai 		if (!path)
3213f3fc0b0bSTakashi Iwai 			continue;
32144e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3215f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3216f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3217f3fc0b0bSTakashi Iwai 
3218f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3219967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3220967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3221f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
32226194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3223f3fc0b0bSTakashi Iwai 			imux_added = true;
3224f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3225f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3226f3fc0b0bSTakashi Iwai 		}
3227f3fc0b0bSTakashi Iwai 	}
3228f3fc0b0bSTakashi Iwai 
3229f3fc0b0bSTakashi Iwai 	return 0;
3230f3fc0b0bSTakashi Iwai }
3231f3fc0b0bSTakashi Iwai 
32321da177e4SLinus Torvalds /*
3233352f7f91STakashi Iwai  * create playback/capture controls for input pins
32341da177e4SLinus Torvalds  */
32359dba205bSTakashi Iwai 
3236c970042cSTakashi Iwai /* fill the label for each input at first */
3237c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3238c970042cSTakashi Iwai {
3239c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3240c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3241c970042cSTakashi Iwai 	int i;
3242c970042cSTakashi Iwai 
3243c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3244c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3245c970042cSTakashi Iwai 		const char *label;
3246c970042cSTakashi Iwai 		int j, idx;
3247c970042cSTakashi Iwai 
3248c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3249c970042cSTakashi Iwai 			continue;
3250c970042cSTakashi Iwai 
3251c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3252c970042cSTakashi Iwai 		idx = 0;
32538e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3254c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3255c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3256c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3257c970042cSTakashi Iwai 				break;
3258c970042cSTakashi Iwai 			}
3259c970042cSTakashi Iwai 		}
3260c970042cSTakashi Iwai 
3261c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3262c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3263c970042cSTakashi Iwai 	}
3264c970042cSTakashi Iwai 
3265c970042cSTakashi Iwai 	return 0;
3266c970042cSTakashi Iwai }
3267c970042cSTakashi Iwai 
32689dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
32699dba205bSTakashi Iwai 
3270352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3271a7da6ce5STakashi Iwai {
3272352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3273352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3274352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3275352f7f91STakashi Iwai 	int num_adcs;
3276c970042cSTakashi Iwai 	int i, err;
32772c12c30dSTakashi Iwai 	unsigned int val;
3278a7da6ce5STakashi Iwai 
3279352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3280352f7f91STakashi Iwai 	if (num_adcs < 0)
3281352f7f91STakashi Iwai 		return 0;
3282352f7f91STakashi Iwai 
3283c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3284c970042cSTakashi Iwai 	if (err < 0)
3285c970042cSTakashi Iwai 		return err;
3286c970042cSTakashi Iwai 
3287352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3288352f7f91STakashi Iwai 		hda_nid_t pin;
3289352f7f91STakashi Iwai 
3290352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3291352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3292352f7f91STakashi Iwai 			continue;
3293352f7f91STakashi Iwai 
32942c12c30dSTakashi Iwai 		val = PIN_IN;
32952c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
32962c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
32973e1b0c4aSTakashi Iwai 		if (pin != spec->hp_mic_pin &&
32983e1b0c4aSTakashi Iwai 		    !snd_hda_codec_get_pin_target(codec, pin))
32992c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
33002c12c30dSTakashi Iwai 
3301352f7f91STakashi Iwai 		if (mixer) {
3302352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3303196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3304c970042cSTakashi Iwai 						       spec->input_labels[i],
3305c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3306c970042cSTakashi Iwai 						       mixer);
3307a7da6ce5STakashi Iwai 				if (err < 0)
3308a7da6ce5STakashi Iwai 					return err;
3309a7da6ce5STakashi Iwai 			}
3310352f7f91STakashi Iwai 		}
3311352f7f91STakashi Iwai 
3312c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3313c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3314f3fc0b0bSTakashi Iwai 		if (err < 0)
3315f3fc0b0bSTakashi Iwai 			return err;
331629476558STakashi Iwai 
3317f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
331829476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
331929476558STakashi Iwai 			if (err < 0)
332029476558STakashi Iwai 				return err;
332129476558STakashi Iwai 		}
3322352f7f91STakashi Iwai 	}
3323f3fc0b0bSTakashi Iwai 
3324f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
332574f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
33269dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3327f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3328f3fc0b0bSTakashi Iwai 		if (err < 0)
3329f3fc0b0bSTakashi Iwai 			return err;
333082d04e10STakashi Iwai 		else
333182d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3332352f7f91STakashi Iwai 	}
3333352f7f91STakashi Iwai 
3334a7da6ce5STakashi Iwai 	return 0;
3335a7da6ce5STakashi Iwai }
3336a7da6ce5STakashi Iwai 
33371da177e4SLinus Torvalds 
3338352f7f91STakashi Iwai /*
3339352f7f91STakashi Iwai  * input source mux
3340352f7f91STakashi Iwai  */
3341352f7f91STakashi Iwai 
3342c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3343c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3344352f7f91STakashi Iwai {
3345352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3346b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3347b56fa1edSDavid Henningsson 		snd_BUG();
3348b56fa1edSDavid Henningsson 		return NULL;
3349b56fa1edSDavid Henningsson 	}
3350352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3351352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3352d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3353b56fa1edSDavid Henningsson 		snd_BUG();
3354b56fa1edSDavid Henningsson 		return NULL;
3355b56fa1edSDavid Henningsson 	}
3356c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
335797ec558aSTakashi Iwai }
3358352f7f91STakashi Iwai 
3359352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3360352f7f91STakashi Iwai 		      unsigned int idx);
3361352f7f91STakashi Iwai 
3362352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3363352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3364352f7f91STakashi Iwai {
3365352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3366352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3367352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3368352f7f91STakashi Iwai }
3369352f7f91STakashi Iwai 
3370352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3371352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3372352f7f91STakashi Iwai {
3373352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3374352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
33752a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
33762a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3377352f7f91STakashi Iwai 
3378352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
33791da177e4SLinus Torvalds 	return 0;
33801da177e4SLinus Torvalds }
33811da177e4SLinus Torvalds 
3382352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3383352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
33841da177e4SLinus Torvalds {
3385352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
33862a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3387352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3388352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3389352f7f91STakashi Iwai }
3390352f7f91STakashi Iwai 
3391352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
33921da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3393352f7f91STakashi Iwai 	.name = "Input Source",
3394352f7f91STakashi Iwai 	.info = mux_enum_info,
3395352f7f91STakashi Iwai 	.get = mux_enum_get,
3396352f7f91STakashi Iwai 	.put = mux_enum_put,
33971da177e4SLinus Torvalds };
3398071c73adSTakashi Iwai 
339947d46abbSTakashi Iwai /*
340047d46abbSTakashi Iwai  * capture volume and capture switch ctls
340147d46abbSTakashi Iwai  */
340247d46abbSTakashi Iwai 
3403352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3404352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3405071c73adSTakashi Iwai 
340647d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3407352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3408352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3409352f7f91STakashi Iwai 			  put_call_t func, int type)
3410352f7f91STakashi Iwai {
3411352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3412352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3413352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3414352f7f91STakashi Iwai 	struct nid_path *path;
3415352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3416071c73adSTakashi Iwai 
3417352f7f91STakashi Iwai 	imux = &spec->input_mux;
3418a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3419352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
3420352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3421c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3422c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3423352f7f91STakashi Iwai 			continue;
3424352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3425352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3426352f7f91STakashi Iwai 		if (err < 0)
3427a551d914STakashi Iwai 			break;
3428352f7f91STakashi Iwai 	}
3429352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3430352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
34317fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3432352f7f91STakashi Iwai 	return err;
3433352f7f91STakashi Iwai }
3434352f7f91STakashi Iwai 
3435352f7f91STakashi Iwai /* capture volume ctl callbacks */
3436352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3437352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3438352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3439352f7f91STakashi Iwai 
3440352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3441352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3442352f7f91STakashi Iwai {
3443352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3444352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3445352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3446352f7f91STakashi Iwai }
3447352f7f91STakashi Iwai 
3448352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3449352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3450352f7f91STakashi Iwai 	.name = "Capture Volume",
3451352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3452352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3453352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3454352f7f91STakashi Iwai 	.info = cap_vol_info,
3455352f7f91STakashi Iwai 	.get = cap_vol_get,
3456352f7f91STakashi Iwai 	.put = cap_vol_put,
3457352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3458352f7f91STakashi Iwai };
3459352f7f91STakashi Iwai 
3460352f7f91STakashi Iwai /* capture switch ctl callbacks */
3461352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3462352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3463352f7f91STakashi Iwai 
3464352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3465352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3466352f7f91STakashi Iwai {
3467a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3468352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3469352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3470352f7f91STakashi Iwai }
3471352f7f91STakashi Iwai 
3472352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3473352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3474352f7f91STakashi Iwai 	.name = "Capture Switch",
3475352f7f91STakashi Iwai 	.info = cap_sw_info,
3476352f7f91STakashi Iwai 	.get = cap_sw_get,
3477352f7f91STakashi Iwai 	.put = cap_sw_put,
3478352f7f91STakashi Iwai };
3479352f7f91STakashi Iwai 
3480352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3481352f7f91STakashi Iwai {
3482352f7f91STakashi Iwai 	hda_nid_t nid;
3483352f7f91STakashi Iwai 	int i, depth;
3484352f7f91STakashi Iwai 
3485352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3486352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3487352f7f91STakashi Iwai 		if (depth >= path->depth)
3488352f7f91STakashi Iwai 			return -EINVAL;
3489352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3490352f7f91STakashi Iwai 		nid = path->path[i];
3491352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3492352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3493352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3494352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3495352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3496352f7f91STakashi Iwai 				int idx = path->idx[i];
3497352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3498352f7f91STakashi Iwai 					idx = 0;
3499352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3500352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3501352f7f91STakashi Iwai 			}
3502352f7f91STakashi Iwai 		}
3503352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3504352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3505352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3506352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3507352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3508352f7f91STakashi Iwai 				int idx = path->idx[i];
3509352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3510352f7f91STakashi Iwai 					idx = 0;
3511352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3512352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3513352f7f91STakashi Iwai 			}
3514352f7f91STakashi Iwai 		}
3515352f7f91STakashi Iwai 	}
3516352f7f91STakashi Iwai 	return 0;
3517352f7f91STakashi Iwai }
3518352f7f91STakashi Iwai 
3519352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3520352f7f91STakashi Iwai {
3521352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3522352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3523352f7f91STakashi Iwai 	unsigned int val;
3524352f7f91STakashi Iwai 	int i;
3525352f7f91STakashi Iwai 
3526352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3527352f7f91STakashi Iwai 		return false;
3528352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3529352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3530352f7f91STakashi Iwai 			continue;
3531352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3532352f7f91STakashi Iwai 			return false;
3533352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3534352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3535352f7f91STakashi Iwai 	}
3536352f7f91STakashi Iwai 	return false;
3537352f7f91STakashi Iwai }
3538352f7f91STakashi Iwai 
3539a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3540a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3541a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3542a35bd1e3STakashi Iwai {
3543a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3544a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3545a35bd1e3STakashi Iwai 	int ret;
3546a35bd1e3STakashi Iwai 
3547a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3548a35bd1e3STakashi Iwai 	if (ret < 0)
3549a35bd1e3STakashi Iwai 		return ret;
3550a35bd1e3STakashi Iwai 
3551a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
35527fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3553a35bd1e3STakashi Iwai 
3554a35bd1e3STakashi Iwai 	return ret;
3555a35bd1e3STakashi Iwai }
3556a35bd1e3STakashi Iwai 
3557352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3558352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3559352f7f91STakashi Iwai 			      bool inv_dmic)
3560352f7f91STakashi Iwai {
3561352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3562975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3563352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3564352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3565352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3566a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai 	if (!ctl)
3569352f7f91STakashi Iwai 		return 0;
3570352f7f91STakashi Iwai 
3571352f7f91STakashi Iwai 	if (label)
3572352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3573352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3574352f7f91STakashi Iwai 	else
3575352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3576352f7f91STakashi Iwai 			 "Capture %s", sfx);
3577a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3578352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3579a35bd1e3STakashi Iwai 	if (!knew)
3580a35bd1e3STakashi Iwai 		return -ENOMEM;
3581a90229e0STakashi Iwai 	if (is_switch)
3582a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3583a35bd1e3STakashi Iwai 	if (!inv_dmic)
3584a35bd1e3STakashi Iwai 		return 0;
3585352f7f91STakashi Iwai 
3586352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3587352f7f91STakashi Iwai 	if (label)
3588352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3589352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3590352f7f91STakashi Iwai 	else
3591352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3592352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3593a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3594352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3595a35bd1e3STakashi Iwai 	if (!knew)
3596a35bd1e3STakashi Iwai 		return -ENOMEM;
3597a90229e0STakashi Iwai 	if (is_switch)
3598a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3599a35bd1e3STakashi Iwai 	return 0;
3600352f7f91STakashi Iwai }
3601352f7f91STakashi Iwai 
3602352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3603352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3604352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3605352f7f91STakashi Iwai 				     bool inv_dmic)
3606352f7f91STakashi Iwai {
3607352f7f91STakashi Iwai 	int err;
3608352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3609352f7f91STakashi Iwai 	if (err < 0)
3610352f7f91STakashi Iwai 		return err;
3611352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3612071c73adSTakashi Iwai 	if (err < 0)
3613071c73adSTakashi Iwai 		return err;
3614071c73adSTakashi Iwai 	return 0;
36151da177e4SLinus Torvalds }
3616071c73adSTakashi Iwai 
3617352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3618352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3619352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3620352f7f91STakashi Iwai {
3621352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3622352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3623352f7f91STakashi Iwai 
3624352f7f91STakashi Iwai 	if (vol_ctl) {
362512c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3626352f7f91STakashi Iwai 		if (!knew)
3627352f7f91STakashi Iwai 			return -ENOMEM;
3628352f7f91STakashi Iwai 		knew->index = idx;
3629352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3630352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3631352f7f91STakashi Iwai 	}
3632352f7f91STakashi Iwai 	if (sw_ctl) {
363312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3634352f7f91STakashi Iwai 		if (!knew)
3635352f7f91STakashi Iwai 			return -ENOMEM;
3636352f7f91STakashi Iwai 		knew->index = idx;
3637352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3638352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3639352f7f91STakashi Iwai 	}
3640352f7f91STakashi Iwai 	return 0;
3641352f7f91STakashi Iwai }
3642352f7f91STakashi Iwai 
3643352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3644352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3645352f7f91STakashi Iwai {
3646352f7f91STakashi Iwai 	struct nid_path *path;
3647352f7f91STakashi Iwai 	unsigned int ctl;
3648352f7f91STakashi Iwai 	int i;
3649352f7f91STakashi Iwai 
3650c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3651352f7f91STakashi Iwai 	if (!path)
3652352f7f91STakashi Iwai 		return 0;
3653352f7f91STakashi Iwai 	ctl = path->ctls[type];
3654352f7f91STakashi Iwai 	if (!ctl)
3655352f7f91STakashi Iwai 		return 0;
3656352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3657c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3658352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3659352f7f91STakashi Iwai 			return 0;
3660352f7f91STakashi Iwai 	}
3661352f7f91STakashi Iwai 	return ctl;
3662352f7f91STakashi Iwai }
3663352f7f91STakashi Iwai 
3664352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3665352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3666352f7f91STakashi Iwai {
3667352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3668352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3669c970042cSTakashi Iwai 	int i, err, type;
3670352f7f91STakashi Iwai 
3671352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3672352f7f91STakashi Iwai 		bool inv_dmic;
3673c970042cSTakashi Iwai 		int idx;
36749dba205bSTakashi Iwai 
3675c970042cSTakashi Iwai 		idx = imux->items[i].index;
3676c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
36779dba205bSTakashi Iwai 			continue;
3678352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3679352f7f91STakashi Iwai 
3680352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3681c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3682c970042cSTakashi Iwai 						 spec->input_labels[idx],
3683c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3684c970042cSTakashi Iwai 						 type,
3685352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3686352f7f91STakashi Iwai 						 inv_dmic);
3687d13bd412STakashi Iwai 			if (err < 0)
3688071c73adSTakashi Iwai 				return err;
3689352f7f91STakashi Iwai 		}
3690352f7f91STakashi Iwai 	}
3691071c73adSTakashi Iwai 	return 0;
3692352f7f91STakashi Iwai }
3693071c73adSTakashi Iwai 
3694352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3695352f7f91STakashi Iwai {
3696352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3697352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3698352f7f91STakashi Iwai 	int i, n, nums, err;
3699352f7f91STakashi Iwai 
3700352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3701352f7f91STakashi Iwai 		nums = 1;
3702352f7f91STakashi Iwai 	else
3703352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3704352f7f91STakashi Iwai 
3705352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3706352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3707624d914dSTakashi Iwai 		const char *name;
3708624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3709624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3710352f7f91STakashi Iwai 		if (!knew)
3711352f7f91STakashi Iwai 			return -ENOMEM;
3712352f7f91STakashi Iwai 		knew->count = nums;
3713352f7f91STakashi Iwai 	}
3714352f7f91STakashi Iwai 
3715352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3716352f7f91STakashi Iwai 		bool multi = false;
371799a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3718352f7f91STakashi Iwai 		bool inv_dmic = false;
3719352f7f91STakashi Iwai 		int vol, sw;
3720352f7f91STakashi Iwai 
3721352f7f91STakashi Iwai 		vol = sw = 0;
3722352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3723352f7f91STakashi Iwai 			struct nid_path *path;
3724c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3725352f7f91STakashi Iwai 			if (!path)
3726352f7f91STakashi Iwai 				continue;
3727352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3728352f7f91STakashi Iwai 			if (!vol)
3729352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
373099a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3731352f7f91STakashi Iwai 				multi = true;
373299a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
373399a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
373499a5592dSDavid Henningsson 					multi_cap_vol = true;
373599a5592dSDavid Henningsson 			}
3736352f7f91STakashi Iwai 			if (!sw)
3737352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
373899a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3739352f7f91STakashi Iwai 				multi = true;
374099a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
374199a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
374299a5592dSDavid Henningsson 					multi_cap_vol = true;
374399a5592dSDavid Henningsson 			}
3744352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3745352f7f91STakashi Iwai 				inv_dmic = true;
3746352f7f91STakashi Iwai 		}
3747352f7f91STakashi Iwai 
3748352f7f91STakashi Iwai 		if (!multi)
3749352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3750352f7f91STakashi Iwai 							inv_dmic);
3751ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3752352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3753352f7f91STakashi Iwai 		else
3754352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3755d13bd412STakashi Iwai 		if (err < 0)
3756071c73adSTakashi Iwai 			return err;
3757071c73adSTakashi Iwai 	}
3758071c73adSTakashi Iwai 
37591da177e4SLinus Torvalds 	return 0;
37601da177e4SLinus Torvalds }
37611da177e4SLinus Torvalds 
3762352f7f91STakashi Iwai /*
3763352f7f91STakashi Iwai  * add mic boosts if needed
3764352f7f91STakashi Iwai  */
37656f7c83afSTakashi Iwai 
37666f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
37676f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
37686f7c83afSTakashi Iwai 			    int dir, int idx)
37696f7c83afSTakashi Iwai {
37706f7c83afSTakashi Iwai 	unsigned int step;
37716f7c83afSTakashi Iwai 
37726f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
37736f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
37746f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
37756f7c83afSTakashi Iwai 		return false;
37766f7c83afSTakashi Iwai 
37776f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
37786f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
37796f7c83afSTakashi Iwai 	if (step < 0x20)
37806f7c83afSTakashi Iwai 		return false;
37816f7c83afSTakashi Iwai 	return true;
37826f7c83afSTakashi Iwai }
37836f7c83afSTakashi Iwai 
37846f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
37856f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
37866f7c83afSTakashi Iwai 				       struct nid_path *path)
37876f7c83afSTakashi Iwai {
37886f7c83afSTakashi Iwai 	unsigned int val = 0;
37896f7c83afSTakashi Iwai 	hda_nid_t nid;
37906f7c83afSTakashi Iwai 	int depth;
37916f7c83afSTakashi Iwai 
37926f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
37936f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
37946f7c83afSTakashi Iwai 			break;
37956f7c83afSTakashi Iwai 		nid = path->path[depth];
37966f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
37976f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
37986f7c83afSTakashi Iwai 			break;
37996f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
38006f7c83afSTakashi Iwai 					   path->idx[depth])) {
38016f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
38026f7c83afSTakashi Iwai 						  HDA_INPUT);
38036f7c83afSTakashi Iwai 			break;
38046f7c83afSTakashi Iwai 		}
38056f7c83afSTakashi Iwai 	}
38066f7c83afSTakashi Iwai 
38076f7c83afSTakashi Iwai 	return val;
38086f7c83afSTakashi Iwai }
38096f7c83afSTakashi Iwai 
3810352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3811352f7f91STakashi Iwai {
3812352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3813352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
38146f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3815a35bd1e3STakashi Iwai 	int i;
3816352f7f91STakashi Iwai 
38176f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
38186f7c83afSTakashi Iwai 		return 0;
38196f7c83afSTakashi Iwai 
38206f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3821352f7f91STakashi Iwai 		struct nid_path *path;
3822352f7f91STakashi Iwai 		unsigned int val;
38236f7c83afSTakashi Iwai 		int idx;
3824975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3825352f7f91STakashi Iwai 
38266f7c83afSTakashi Iwai 		idx = imux->items[i].index;
38276f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
382802aba550SDavid Henningsson 			continue;
382902aba550SDavid Henningsson 
38306f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
38311799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
38326f7c83afSTakashi Iwai 			continue;
38336f7c83afSTakashi Iwai 
38346f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
38356f7c83afSTakashi Iwai 		if (!path)
38366f7c83afSTakashi Iwai 			continue;
38376f7c83afSTakashi Iwai 
38386f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
38396f7c83afSTakashi Iwai 		if (!val)
38406f7c83afSTakashi Iwai 			continue;
38416f7c83afSTakashi Iwai 
38426f7c83afSTakashi Iwai 		/* create a boost control */
3843352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
38446f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3845a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3846a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3847a35bd1e3STakashi Iwai 			return -ENOMEM;
3848352f7f91STakashi Iwai 
3849352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3850352f7f91STakashi Iwai 	}
3851352f7f91STakashi Iwai 	return 0;
3852352f7f91STakashi Iwai }
3853352f7f91STakashi Iwai 
3854352f7f91STakashi Iwai /*
3855352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3856352f7f91STakashi Iwai  */
3857352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3858352f7f91STakashi Iwai {
3859352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
38600c8c0f56STakashi Iwai 	struct nid_path *path;
3861352f7f91STakashi Iwai 	int i, nums;
38622c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3863352f7f91STakashi Iwai 
3864352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3865352f7f91STakashi Iwai 	nums = 0;
3866352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
38672c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3868352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3869352f7f91STakashi Iwai 		if (!dig_nid)
3870352f7f91STakashi Iwai 			continue;
38713ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
38720c8c0f56STakashi Iwai 		if (!path)
3873352f7f91STakashi Iwai 			continue;
38744e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
3875e1284af7STakashi Iwai 		path->active = true;
38766b275b14STakashi Iwai 		path->pin_fixed = true; /* no jack detection */
3877196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
38782c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3879352f7f91STakashi Iwai 		if (!nums) {
3880352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3881352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3882352f7f91STakashi Iwai 		} else {
3883352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3884352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3885352f7f91STakashi Iwai 				break;
3886352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3887352f7f91STakashi Iwai 		}
3888352f7f91STakashi Iwai 		nums++;
3889352f7f91STakashi Iwai 	}
3890352f7f91STakashi Iwai 
3891352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
38922c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
38937639a06cSTakashi Iwai 		for_each_hda_codec_node(dig_nid, codec) {
3894352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3895352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3896352f7f91STakashi Iwai 				continue;
3897352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3898352f7f91STakashi Iwai 				continue;
38992c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3900352f7f91STakashi Iwai 			if (path) {
39014e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
3902352f7f91STakashi Iwai 				path->active = true;
39036b275b14STakashi Iwai 				path->pin_fixed = true; /* no jack */
3904352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
39052430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
39062c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3907352f7f91STakashi Iwai 				break;
3908352f7f91STakashi Iwai 			}
3909352f7f91STakashi Iwai 		}
3910352f7f91STakashi Iwai 	}
3911352f7f91STakashi Iwai }
3912352f7f91STakashi Iwai 
39131da177e4SLinus Torvalds 
39141da177e4SLinus Torvalds /*
3915352f7f91STakashi Iwai  * input MUX handling
39161da177e4SLinus Torvalds  */
39171da177e4SLinus Torvalds 
3918352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3919352f7f91STakashi Iwai 
3920352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3921352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3922352f7f91STakashi Iwai 		      unsigned int idx)
3923352f7f91STakashi Iwai {
3924352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3925352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
392655196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3927352f7f91STakashi Iwai 
3928352f7f91STakashi Iwai 	imux = &spec->input_mux;
3929352f7f91STakashi Iwai 	if (!imux->num_items)
39301da177e4SLinus Torvalds 		return 0;
39311da177e4SLinus Torvalds 
3932352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3933352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3934352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3935352f7f91STakashi Iwai 		return 0;
3936352f7f91STakashi Iwai 
393755196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
393855196fffSTakashi Iwai 	if (!old_path)
3939352f7f91STakashi Iwai 		return 0;
394055196fffSTakashi Iwai 	if (old_path->active)
394155196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3942352f7f91STakashi Iwai 
3943352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3944352f7f91STakashi Iwai 
3945967303daSTakashi Iwai 	if (spec->hp_mic)
3946967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3947352f7f91STakashi Iwai 
3948352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3949352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3950352f7f91STakashi Iwai 
3951c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3952352f7f91STakashi Iwai 	if (!path)
3953352f7f91STakashi Iwai 		return 0;
3954352f7f91STakashi Iwai 	if (path->active)
3955352f7f91STakashi Iwai 		return 0;
3956352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3957352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
39587fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
395955196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
39601da177e4SLinus Torvalds 	return 1;
39611da177e4SLinus Torvalds }
39621da177e4SLinus Torvalds 
3963e6feb5d0STakashi Iwai /* power up/down widgets in the all paths that match with the given NID
3964e6feb5d0STakashi Iwai  * as terminals (either start- or endpoint)
3965e6feb5d0STakashi Iwai  *
3966e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
3967e6feb5d0STakashi Iwai  */
3968e6feb5d0STakashi Iwai static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
3969e6feb5d0STakashi Iwai 				int pin_state, int stream_state)
3970e6feb5d0STakashi Iwai {
3971e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3972e6feb5d0STakashi Iwai 	hda_nid_t last, changed = 0;
3973e6feb5d0STakashi Iwai 	struct nid_path *path;
3974e6feb5d0STakashi Iwai 	int n;
3975e6feb5d0STakashi Iwai 
3976e6feb5d0STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
3977e6feb5d0STakashi Iwai 		path = snd_array_elem(&spec->paths, n);
3978e6feb5d0STakashi Iwai 		if (path->path[0] == nid ||
3979e6feb5d0STakashi Iwai 		    path->path[path->depth - 1] == nid) {
3980e6feb5d0STakashi Iwai 			bool pin_old = path->pin_enabled;
3981e6feb5d0STakashi Iwai 			bool stream_old = path->stream_enabled;
3982e6feb5d0STakashi Iwai 
3983e6feb5d0STakashi Iwai 			if (pin_state >= 0)
3984e6feb5d0STakashi Iwai 				path->pin_enabled = pin_state;
3985e6feb5d0STakashi Iwai 			if (stream_state >= 0)
3986e6feb5d0STakashi Iwai 				path->stream_enabled = stream_state;
39876b275b14STakashi Iwai 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
39886b275b14STakashi Iwai 			    || path->stream_enabled != stream_old) {
3989e6feb5d0STakashi Iwai 				last = path_power_update(codec, path, true);
3990e6feb5d0STakashi Iwai 				if (last)
3991e6feb5d0STakashi Iwai 					changed = last;
3992e6feb5d0STakashi Iwai 			}
3993e6feb5d0STakashi Iwai 		}
3994e6feb5d0STakashi Iwai 	}
3995e6feb5d0STakashi Iwai 	return changed;
3996e6feb5d0STakashi Iwai }
3997e6feb5d0STakashi Iwai 
3998d5ac0100STakashi Iwai /* check the jack status for power control */
3999d5ac0100STakashi Iwai static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4000d5ac0100STakashi Iwai {
4001d5ac0100STakashi Iwai 	if (!is_jack_detectable(codec, pin))
4002d5ac0100STakashi Iwai 		return true;
4003d5ac0100STakashi Iwai 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4004d5ac0100STakashi Iwai }
4005d5ac0100STakashi Iwai 
4006e6feb5d0STakashi Iwai /* power up/down the paths of the given pin according to the jack state;
4007e6feb5d0STakashi Iwai  * power = 0/1 : only power up/down if it matches with the jack state,
4008e6feb5d0STakashi Iwai  *       < 0   : force power up/down to follow the jack sate
4009e6feb5d0STakashi Iwai  *
4010e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4011e6feb5d0STakashi Iwai  */
4012e6feb5d0STakashi Iwai static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4013e6feb5d0STakashi Iwai 				    int power)
4014e6feb5d0STakashi Iwai {
4015e6feb5d0STakashi Iwai 	bool on;
4016e6feb5d0STakashi Iwai 
4017967b1307STakashi Iwai 	if (!codec->power_save_node)
4018e6feb5d0STakashi Iwai 		return 0;
4019e6feb5d0STakashi Iwai 
4020d5ac0100STakashi Iwai 	on = detect_pin_state(codec, pin);
4021d5ac0100STakashi Iwai 
4022e6feb5d0STakashi Iwai 	if (power >= 0 && on != power)
4023e6feb5d0STakashi Iwai 		return 0;
4024e6feb5d0STakashi Iwai 	return set_path_power(codec, pin, on, -1);
4025e6feb5d0STakashi Iwai }
4026e6feb5d0STakashi Iwai 
4027e6feb5d0STakashi Iwai static void pin_power_callback(struct hda_codec *codec,
4028e6feb5d0STakashi Iwai 			       struct hda_jack_callback *jack,
4029e6feb5d0STakashi Iwai 			       bool on)
4030e6feb5d0STakashi Iwai {
4031e6feb5d0STakashi Iwai 	if (jack && jack->tbl->nid)
4032e6feb5d0STakashi Iwai 		sync_power_state_change(codec,
4033e6feb5d0STakashi Iwai 					set_pin_power_jack(codec, jack->tbl->nid, on));
4034e6feb5d0STakashi Iwai }
4035e6feb5d0STakashi Iwai 
4036e6feb5d0STakashi Iwai /* callback only doing power up -- called at first */
4037e6feb5d0STakashi Iwai static void pin_power_up_callback(struct hda_codec *codec,
4038e6feb5d0STakashi Iwai 				  struct hda_jack_callback *jack)
4039e6feb5d0STakashi Iwai {
4040e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, true);
4041e6feb5d0STakashi Iwai }
4042e6feb5d0STakashi Iwai 
4043e6feb5d0STakashi Iwai /* callback only doing power down -- called at last */
4044e6feb5d0STakashi Iwai static void pin_power_down_callback(struct hda_codec *codec,
4045e6feb5d0STakashi Iwai 				    struct hda_jack_callback *jack)
4046e6feb5d0STakashi Iwai {
4047e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, false);
4048e6feb5d0STakashi Iwai }
4049e6feb5d0STakashi Iwai 
4050e6feb5d0STakashi Iwai /* set up the power up/down callbacks */
4051e6feb5d0STakashi Iwai static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4052e6feb5d0STakashi Iwai 			       const hda_nid_t *pins, bool on)
4053e6feb5d0STakashi Iwai {
4054e6feb5d0STakashi Iwai 	int i;
4055e6feb5d0STakashi Iwai 	hda_jack_callback_fn cb =
4056e6feb5d0STakashi Iwai 		on ? pin_power_up_callback : pin_power_down_callback;
4057e6feb5d0STakashi Iwai 
4058e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++) {
4059e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4060e6feb5d0STakashi Iwai 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4061e6feb5d0STakashi Iwai 		else
4062e6feb5d0STakashi Iwai 			set_path_power(codec, pins[i], true, -1);
4063e6feb5d0STakashi Iwai 	}
4064e6feb5d0STakashi Iwai }
4065e6feb5d0STakashi Iwai 
4066e6feb5d0STakashi Iwai /* enabled power callback to each available I/O pin with jack detections;
4067e6feb5d0STakashi Iwai  * the digital I/O pins are excluded because of the unreliable detectsion
4068e6feb5d0STakashi Iwai  */
4069e6feb5d0STakashi Iwai static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4070e6feb5d0STakashi Iwai {
4071e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4072e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4073e6feb5d0STakashi Iwai 	int i;
4074e6feb5d0STakashi Iwai 
4075967b1307STakashi Iwai 	if (!codec->power_save_node)
4076e6feb5d0STakashi Iwai 		return;
4077e6feb5d0STakashi Iwai 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4078e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4079e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4080e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4081e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4082e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4083e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4084e6feb5d0STakashi Iwai }
4085e6feb5d0STakashi Iwai 
4086e6feb5d0STakashi Iwai /* sync path power up/down with the jack states of given pins */
4087e6feb5d0STakashi Iwai static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4088e6feb5d0STakashi Iwai 				const hda_nid_t *pins)
4089e6feb5d0STakashi Iwai {
4090e6feb5d0STakashi Iwai 	int i;
4091e6feb5d0STakashi Iwai 
4092e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++)
4093e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4094e6feb5d0STakashi Iwai 			set_pin_power_jack(codec, pins[i], -1);
4095e6feb5d0STakashi Iwai }
4096e6feb5d0STakashi Iwai 
4097e6feb5d0STakashi Iwai /* sync path power up/down with pins; called at init and resume */
4098e6feb5d0STakashi Iwai static void sync_all_pin_power_ctls(struct hda_codec *codec)
4099e6feb5d0STakashi Iwai {
4100e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4101e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4102e6feb5d0STakashi Iwai 	int i;
4103e6feb5d0STakashi Iwai 
4104967b1307STakashi Iwai 	if (!codec->power_save_node)
4105e6feb5d0STakashi Iwai 		return;
4106e6feb5d0STakashi Iwai 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4107e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4108e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4109e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4110e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4111e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4112e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4113e6feb5d0STakashi Iwai }
41141da177e4SLinus Torvalds 
41155ccf835cSTakashi Iwai /* add fake paths if not present yet */
41165ccf835cSTakashi Iwai static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
41175ccf835cSTakashi Iwai 			   int num_pins, const hda_nid_t *pins)
41185ccf835cSTakashi Iwai {
41195ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41205ccf835cSTakashi Iwai 	struct nid_path *path;
41215ccf835cSTakashi Iwai 	int i;
41225ccf835cSTakashi Iwai 
41235ccf835cSTakashi Iwai 	for (i = 0; i < num_pins; i++) {
41245ccf835cSTakashi Iwai 		if (!pins[i])
41255ccf835cSTakashi Iwai 			break;
41265ccf835cSTakashi Iwai 		if (get_nid_path(codec, nid, pins[i], 0))
41275ccf835cSTakashi Iwai 			continue;
41285ccf835cSTakashi Iwai 		path = snd_array_new(&spec->paths);
41295ccf835cSTakashi Iwai 		if (!path)
41305ccf835cSTakashi Iwai 			return -ENOMEM;
41315ccf835cSTakashi Iwai 		memset(path, 0, sizeof(*path));
41325ccf835cSTakashi Iwai 		path->depth = 2;
41335ccf835cSTakashi Iwai 		path->path[0] = nid;
41345ccf835cSTakashi Iwai 		path->path[1] = pins[i];
41355ccf835cSTakashi Iwai 		path->active = true;
41365ccf835cSTakashi Iwai 	}
41375ccf835cSTakashi Iwai 	return 0;
41385ccf835cSTakashi Iwai }
41395ccf835cSTakashi Iwai 
41405ccf835cSTakashi Iwai /* create fake paths to all outputs from beep */
41415ccf835cSTakashi Iwai static int add_fake_beep_paths(struct hda_codec *codec)
41425ccf835cSTakashi Iwai {
41435ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41445ccf835cSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
41455ccf835cSTakashi Iwai 	hda_nid_t nid = spec->beep_nid;
41465ccf835cSTakashi Iwai 	int err;
41475ccf835cSTakashi Iwai 
4148967b1307STakashi Iwai 	if (!codec->power_save_node || !nid)
41495ccf835cSTakashi Iwai 		return 0;
41505ccf835cSTakashi Iwai 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
41515ccf835cSTakashi Iwai 	if (err < 0)
41525ccf835cSTakashi Iwai 		return err;
41535ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
41545ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
41555ccf835cSTakashi Iwai 		if (err < 0)
41565ccf835cSTakashi Iwai 			return err;
41575ccf835cSTakashi Iwai 	}
41585ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
41595ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
41605ccf835cSTakashi Iwai 				     cfg->speaker_pins);
41615ccf835cSTakashi Iwai 		if (err < 0)
41625ccf835cSTakashi Iwai 			return err;
41635ccf835cSTakashi Iwai 	}
41645ccf835cSTakashi Iwai 	return 0;
41655ccf835cSTakashi Iwai }
41665ccf835cSTakashi Iwai 
41675ccf835cSTakashi Iwai /* power up/down beep widget and its output paths */
41685ccf835cSTakashi Iwai static void beep_power_hook(struct hda_beep *beep, bool on)
41695ccf835cSTakashi Iwai {
41705ccf835cSTakashi Iwai 	set_path_power(beep->codec, beep->nid, -1, on);
41715ccf835cSTakashi Iwai }
41725ccf835cSTakashi Iwai 
41736b275b14STakashi Iwai /**
41746b275b14STakashi Iwai  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
41756b275b14STakashi Iwai  * @codec: the HDA codec
41766b275b14STakashi Iwai  * @pin: NID of pin to fix
41776b275b14STakashi Iwai  */
41786b275b14STakashi Iwai int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
41796b275b14STakashi Iwai {
41806b275b14STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41816b275b14STakashi Iwai 	struct nid_path *path;
41826b275b14STakashi Iwai 
41836b275b14STakashi Iwai 	path = snd_array_new(&spec->paths);
41846b275b14STakashi Iwai 	if (!path)
41856b275b14STakashi Iwai 		return -ENOMEM;
41866b275b14STakashi Iwai 	memset(path, 0, sizeof(*path));
41876b275b14STakashi Iwai 	path->depth = 1;
41886b275b14STakashi Iwai 	path->path[0] = pin;
41896b275b14STakashi Iwai 	path->active = true;
41906b275b14STakashi Iwai 	path->pin_fixed = true;
41916b275b14STakashi Iwai 	path->stream_enabled = true;
41926b275b14STakashi Iwai 	return 0;
41936b275b14STakashi Iwai }
41946b275b14STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
41956b275b14STakashi Iwai 
41961da177e4SLinus Torvalds /*
4197352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
41981da177e4SLinus Torvalds  */
4199352f7f91STakashi Iwai 
4200352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
4201352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
42021da177e4SLinus Torvalds {
420360ea8ca2STakashi Iwai 	int i;
420460ea8ca2STakashi Iwai 	bool present = false;
42051da177e4SLinus Torvalds 
4206352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4207352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4208352f7f91STakashi Iwai 		if (!nid)
4209352f7f91STakashi Iwai 			break;
42100b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
42110b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
42120b4df931STakashi Iwai 			continue;
421360ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
421460ea8ca2STakashi Iwai 			present = true;
42151da177e4SLinus Torvalds 	}
4216352f7f91STakashi Iwai 	return present;
42171da177e4SLinus Torvalds }
42181da177e4SLinus Torvalds 
4219352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
4220352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
4221e80c60f3STakashi Iwai 			int *paths, bool mute)
42221da177e4SLinus Torvalds {
4223352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4224352f7f91STakashi Iwai 	int i;
42251da177e4SLinus Torvalds 
4226352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4227352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4228967303daSTakashi Iwai 		unsigned int val, oldval;
4229352f7f91STakashi Iwai 		if (!nid)
4230352f7f91STakashi Iwai 			break;
42317eebffd3STakashi Iwai 
4232e6feb5d0STakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4233e6feb5d0STakashi Iwai 		if (oldval & PIN_IN)
4234e6feb5d0STakashi Iwai 			continue; /* no mute for inputs */
4235e6feb5d0STakashi Iwai 
42367eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
4237e80c60f3STakashi Iwai 			struct nid_path *path;
4238e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
4239e80c60f3STakashi Iwai 
4240e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4241e80c60f3STakashi Iwai 			if (!path)
4242e80c60f3STakashi Iwai 				continue;
4243e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4244e80c60f3STakashi Iwai 			if (!mute_nid)
4245e80c60f3STakashi Iwai 				continue;
42467eebffd3STakashi Iwai 			if (mute)
4247e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
42487eebffd3STakashi Iwai 			else
4249e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
42507eebffd3STakashi Iwai 			continue;
4251e6feb5d0STakashi Iwai 		} else {
4252352f7f91STakashi Iwai 			/* don't reset VREF value in case it's controlling
4253352f7f91STakashi Iwai 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4254352f7f91STakashi Iwai 			 */
42552c12c30dSTakashi Iwai 			if (spec->keep_vref_in_automute)
4256967303daSTakashi Iwai 				val = oldval & ~PIN_HP;
42572c12c30dSTakashi Iwai 			else
4258352f7f91STakashi Iwai 				val = 0;
42592c12c30dSTakashi Iwai 			if (!mute)
4260967303daSTakashi Iwai 				val |= oldval;
4261e6feb5d0STakashi Iwai 			/* here we call update_pin_ctl() so that the pinctl is
4262e6feb5d0STakashi Iwai 			 * changed without changing the pinctl target value;
4263e6feb5d0STakashi Iwai 			 * the original target value will be still referred at
4264e6feb5d0STakashi Iwai 			 * the init / resume again
42652c12c30dSTakashi Iwai 			 */
42662c12c30dSTakashi Iwai 			update_pin_ctl(codec, nid, val);
4267e6feb5d0STakashi Iwai 		}
4268e6feb5d0STakashi Iwai 
4269d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
4270967b1307STakashi Iwai 		if (codec->power_save_node) {
4271e6feb5d0STakashi Iwai 			bool on = !mute;
4272e6feb5d0STakashi Iwai 			if (on)
4273d5ac0100STakashi Iwai 				on = detect_pin_state(codec, nid);
4274e6feb5d0STakashi Iwai 			set_path_power(codec, nid, on, -1);
4275e6feb5d0STakashi Iwai 		}
4276352f7f91STakashi Iwai 	}
4277352f7f91STakashi Iwai }
42781da177e4SLinus Torvalds 
4279dda42bd0STakashi Iwai /**
4280dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
4281dda42bd0STakashi Iwai  * @codec: the HDA codec
4282dda42bd0STakashi Iwai  *
4283dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
4284dda42bd0STakashi Iwai  */
42855d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
4286352f7f91STakashi Iwai {
4287352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4288e80c60f3STakashi Iwai 	int *paths;
4289352f7f91STakashi Iwai 	int on;
4290352f7f91STakashi Iwai 
4291352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
4292352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
4293352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
4294352f7f91STakashi Iwai 	 */
4295e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4296e80c60f3STakashi Iwai 		paths = spec->out_paths;
4297e80c60f3STakashi Iwai 	else
4298e80c60f3STakashi Iwai 		paths = spec->hp_paths;
4299352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4300e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4301352f7f91STakashi Iwai 
4302352f7f91STakashi Iwai 	if (!spec->automute_speaker)
4303352f7f91STakashi Iwai 		on = 0;
4304352f7f91STakashi Iwai 	else
4305352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
4306352f7f91STakashi Iwai 	on |= spec->master_mute;
430747b9ddb8STakashi Iwai 	spec->speaker_muted = on;
4308e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4309e80c60f3STakashi Iwai 		paths = spec->out_paths;
4310e80c60f3STakashi Iwai 	else
4311e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
4312352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4313e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
4314352f7f91STakashi Iwai 
4315352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
4316352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4317352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4318352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4319352f7f91STakashi Iwai 		return;
4320352f7f91STakashi Iwai 	if (!spec->automute_lo)
4321352f7f91STakashi Iwai 		on = 0;
4322352f7f91STakashi Iwai 	else
4323352f7f91STakashi Iwai 		on = spec->hp_jack_present;
4324352f7f91STakashi Iwai 	on |= spec->master_mute;
432547b9ddb8STakashi Iwai 	spec->line_out_muted = on;
4326e80c60f3STakashi Iwai 	paths = spec->out_paths;
4327352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4328e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
4329352f7f91STakashi Iwai }
43302698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4331352f7f91STakashi Iwai 
4332352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
4333352f7f91STakashi Iwai {
4334352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4335352f7f91STakashi Iwai 	if (spec->automute_hook)
4336352f7f91STakashi Iwai 		spec->automute_hook(codec);
4337352f7f91STakashi Iwai 	else
43385d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
43397eebffd3STakashi Iwai 
43407eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
43417eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
43427eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4343352f7f91STakashi Iwai }
4344352f7f91STakashi Iwai 
4345dda42bd0STakashi Iwai /**
4346dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4347dda42bd0STakashi Iwai  * @codec: the HDA codec
4348dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4349dda42bd0STakashi Iwai  */
43501a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
43511a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4352352f7f91STakashi Iwai {
4353352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
435492603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
435592603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4356352f7f91STakashi Iwai 
435792603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
435892603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
435992603c59STakashi Iwai 		pins++;
436092603c59STakashi Iwai 		num_pins--;
436192603c59STakashi Iwai 	}
436292603c59STakashi Iwai 
436392603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4364352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4365352f7f91STakashi Iwai 		return;
4366352f7f91STakashi Iwai 	call_update_outputs(codec);
4367352f7f91STakashi Iwai }
43682698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4369352f7f91STakashi Iwai 
4370dda42bd0STakashi Iwai /**
4371dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4372dda42bd0STakashi Iwai  * @codec: the HDA codec
4373dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4374dda42bd0STakashi Iwai  */
43751a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
43761a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4377352f7f91STakashi Iwai {
4378352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4379352f7f91STakashi Iwai 
4380352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4381352f7f91STakashi Iwai 		return;
4382352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4383352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4384352f7f91STakashi Iwai 		return;
4385352f7f91STakashi Iwai 
4386352f7f91STakashi Iwai 	spec->line_jack_present =
4387352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4388352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4389352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4390352f7f91STakashi Iwai 		return;
4391352f7f91STakashi Iwai 	call_update_outputs(codec);
4392352f7f91STakashi Iwai }
43932698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4394352f7f91STakashi Iwai 
4395dda42bd0STakashi Iwai /**
4396dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4397dda42bd0STakashi Iwai  * @codec: the HDA codec
4398dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4399dda42bd0STakashi Iwai  */
44001a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
44011a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4402352f7f91STakashi Iwai {
4403352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4404352f7f91STakashi Iwai 	int i;
4405352f7f91STakashi Iwai 
4406352f7f91STakashi Iwai 	if (!spec->auto_mic)
4407352f7f91STakashi Iwai 		return;
4408352f7f91STakashi Iwai 
4409352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
44100b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
44110b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
44120b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
44130b4df931STakashi Iwai 			continue;
441460ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4415352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4416352f7f91STakashi Iwai 			return;
4417352f7f91STakashi Iwai 		}
4418352f7f91STakashi Iwai 	}
4419352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
44201da177e4SLinus Torvalds }
44212698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
44221da177e4SLinus Torvalds 
442377afe0e9STakashi Iwai /* call appropriate hooks */
44241a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
44251a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
442677afe0e9STakashi Iwai {
442777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
442877afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
442977afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
443077afe0e9STakashi Iwai 	else
443177afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
443277afe0e9STakashi Iwai }
443377afe0e9STakashi Iwai 
443477afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
44351a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
443677afe0e9STakashi Iwai {
443777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
443877afe0e9STakashi Iwai 	if (spec->line_automute_hook)
443977afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
444077afe0e9STakashi Iwai 	else
444177afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
444277afe0e9STakashi Iwai }
444377afe0e9STakashi Iwai 
444477afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
44451a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
444677afe0e9STakashi Iwai {
444777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
444877afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
444977afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
445077afe0e9STakashi Iwai 	else
445177afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
445277afe0e9STakashi Iwai }
445377afe0e9STakashi Iwai 
4454963afde9STakashi Iwai /* update jack retasking */
4455963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4456963afde9STakashi Iwai {
4457963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4458963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4459963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4460963afde9STakashi Iwai }
4461963afde9STakashi Iwai 
44621da177e4SLinus Torvalds /*
4463352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
44641da177e4SLinus Torvalds  */
4465352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4466352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4467352f7f91STakashi Iwai {
4468352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4469352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4470352f7f91STakashi Iwai 	static const char * const texts3[] = {
4471352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
44721da177e4SLinus Torvalds 	};
44731da177e4SLinus Torvalds 
4474352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4475352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4476352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4477352f7f91STakashi Iwai }
4478352f7f91STakashi Iwai 
4479352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4480352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4481352f7f91STakashi Iwai {
4482352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4483352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4484352f7f91STakashi Iwai 	unsigned int val = 0;
4485352f7f91STakashi Iwai 	if (spec->automute_speaker)
4486352f7f91STakashi Iwai 		val++;
4487352f7f91STakashi Iwai 	if (spec->automute_lo)
4488352f7f91STakashi Iwai 		val++;
4489352f7f91STakashi Iwai 
4490352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4491352f7f91STakashi Iwai 	return 0;
4492352f7f91STakashi Iwai }
4493352f7f91STakashi Iwai 
4494352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4495352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4496352f7f91STakashi Iwai {
4497352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4498352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4501352f7f91STakashi Iwai 	case 0:
4502352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4503352f7f91STakashi Iwai 			return 0;
4504352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4505352f7f91STakashi Iwai 		spec->automute_lo = 0;
4506352f7f91STakashi Iwai 		break;
4507352f7f91STakashi Iwai 	case 1:
4508352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4509352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4510352f7f91STakashi Iwai 				return 0;
4511352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4512352f7f91STakashi Iwai 			spec->automute_lo = 0;
4513352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4514352f7f91STakashi Iwai 			if (spec->automute_lo)
4515352f7f91STakashi Iwai 				return 0;
4516352f7f91STakashi Iwai 			spec->automute_lo = 1;
4517352f7f91STakashi Iwai 		} else
4518352f7f91STakashi Iwai 			return -EINVAL;
4519352f7f91STakashi Iwai 		break;
4520352f7f91STakashi Iwai 	case 2:
4521352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4522352f7f91STakashi Iwai 			return -EINVAL;
4523352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4524352f7f91STakashi Iwai 			return 0;
4525352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4526352f7f91STakashi Iwai 		spec->automute_lo = 1;
4527352f7f91STakashi Iwai 		break;
4528352f7f91STakashi Iwai 	default:
4529352f7f91STakashi Iwai 		return -EINVAL;
4530352f7f91STakashi Iwai 	}
4531352f7f91STakashi Iwai 	call_update_outputs(codec);
4532352f7f91STakashi Iwai 	return 1;
4533352f7f91STakashi Iwai }
4534352f7f91STakashi Iwai 
4535352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4536352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4537352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4538352f7f91STakashi Iwai 	.info = automute_mode_info,
4539352f7f91STakashi Iwai 	.get = automute_mode_get,
4540352f7f91STakashi Iwai 	.put = automute_mode_put,
4541352f7f91STakashi Iwai };
4542352f7f91STakashi Iwai 
4543352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4544352f7f91STakashi Iwai {
4545352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4546352f7f91STakashi Iwai 
454712c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4548352f7f91STakashi Iwai 		return -ENOMEM;
4549352f7f91STakashi Iwai 	return 0;
4550352f7f91STakashi Iwai }
4551352f7f91STakashi Iwai 
4552352f7f91STakashi Iwai /*
4553352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4554352f7f91STakashi Iwai  * Set up appropriately if really supported
4555352f7f91STakashi Iwai  */
4556352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4557352f7f91STakashi Iwai {
4558352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4559352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4560352f7f91STakashi Iwai 	int present = 0;
4561352f7f91STakashi Iwai 	int i, err;
4562352f7f91STakashi Iwai 
4563f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4564f72706beSTakashi Iwai 		return 0;
4565f72706beSTakashi Iwai 
4566352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4567352f7f91STakashi Iwai 		present++;
4568352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4569352f7f91STakashi Iwai 		present++;
4570352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4571352f7f91STakashi Iwai 		present++;
4572352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4573352f7f91STakashi Iwai 		return 0;
4574352f7f91STakashi Iwai 
4575352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4576352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4577352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4578352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4579352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4580352f7f91STakashi Iwai 	}
4581352f7f91STakashi Iwai 
4582352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4583352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4584352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4585352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4586352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4587352f7f91STakashi Iwai 	}
4588352f7f91STakashi Iwai 
4589352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4590352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4591352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4592352f7f91STakashi Iwai 			continue;
45934e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
459462f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
459577afe0e9STakashi Iwai 						    call_hp_automute);
4596352f7f91STakashi Iwai 		spec->detect_hp = 1;
4597352f7f91STakashi Iwai 	}
4598352f7f91STakashi Iwai 
4599352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4600352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4601352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4602352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4603352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4604352f7f91STakashi Iwai 					continue;
46054e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4606352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
460777afe0e9STakashi Iwai 								    call_line_automute);
4608352f7f91STakashi Iwai 				spec->detect_lo = 1;
4609352f7f91STakashi Iwai 			}
4610352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4611352f7f91STakashi Iwai 	}
4612352f7f91STakashi Iwai 
4613352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4614352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4615352f7f91STakashi Iwai 
4616352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4617352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4618352f7f91STakashi Iwai 
4619352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4620352f7f91STakashi Iwai 		/* create a control for automute mode */
4621352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4622352f7f91STakashi Iwai 		if (err < 0)
4623352f7f91STakashi Iwai 			return err;
4624352f7f91STakashi Iwai 	}
4625352f7f91STakashi Iwai 	return 0;
4626352f7f91STakashi Iwai }
4627352f7f91STakashi Iwai 
4628352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4629352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4630352f7f91STakashi Iwai {
4631352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4632352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4633352f7f91STakashi Iwai 	int i;
4634352f7f91STakashi Iwai 
4635352f7f91STakashi Iwai 	imux = &spec->input_mux;
4636352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4637352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4638352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4639352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4640352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4641352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4642352f7f91STakashi Iwai 	}
4643352f7f91STakashi Iwai 
4644352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4645352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4646352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4647352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
464877afe0e9STakashi Iwai 						    call_mic_autoswitch);
4649352f7f91STakashi Iwai 	return true;
4650352f7f91STakashi Iwai }
4651352f7f91STakashi Iwai 
4652352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4653352f7f91STakashi Iwai {
4654352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4655352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4656352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4657352f7f91STakashi Iwai }
4658352f7f91STakashi Iwai 
4659352f7f91STakashi Iwai /*
4660352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4661352f7f91STakashi Iwai  * Set up if really supported
4662352f7f91STakashi Iwai  */
4663352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4664352f7f91STakashi Iwai {
4665352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4666352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4667352f7f91STakashi Iwai 	unsigned int types;
4668352f7f91STakashi Iwai 	int i, num_pins;
4669352f7f91STakashi Iwai 
4670d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4671d12daf6fSTakashi Iwai 		return 0;
4672d12daf6fSTakashi Iwai 
4673352f7f91STakashi Iwai 	types = 0;
4674352f7f91STakashi Iwai 	num_pins = 0;
4675352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4676352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4677352f7f91STakashi Iwai 		unsigned int attr;
4678352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4679352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4680352f7f91STakashi Iwai 		if (types & (1 << attr))
4681352f7f91STakashi Iwai 			return 0; /* already occupied */
4682352f7f91STakashi Iwai 		switch (attr) {
4683352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4684352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4685352f7f91STakashi Iwai 				return 0; /* invalid type */
4686352f7f91STakashi Iwai 			break;
4687352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4688352f7f91STakashi Iwai 			return 0; /* invalid entry */
4689352f7f91STakashi Iwai 		default:
4690352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4691352f7f91STakashi Iwai 				return 0; /* invalid type */
4692352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4693352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4694352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4695352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4696352f7f91STakashi Iwai 				return 0; /* no unsol support */
4697352f7f91STakashi Iwai 			break;
4698352f7f91STakashi Iwai 		}
4699352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4700352f7f91STakashi Iwai 			return 0;
4701352f7f91STakashi Iwai 		types |= (1 << attr);
4702352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4703352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4704352f7f91STakashi Iwai 		num_pins++;
4705352f7f91STakashi Iwai 	}
4706352f7f91STakashi Iwai 
4707352f7f91STakashi Iwai 	if (num_pins < 2)
4708352f7f91STakashi Iwai 		return 0;
4709352f7f91STakashi Iwai 
4710352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4711352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4712352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4713352f7f91STakashi Iwai 	 */
4714352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4715352f7f91STakashi Iwai 	     compare_attr, NULL);
4716352f7f91STakashi Iwai 
4717352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4718352f7f91STakashi Iwai 		return 0;
4719352f7f91STakashi Iwai 
4720352f7f91STakashi Iwai 	spec->auto_mic = 1;
4721352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4722352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
47234e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4724352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4725352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4726352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4727352f7f91STakashi Iwai 
4728352f7f91STakashi Iwai 	return 0;
4729352f7f91STakashi Iwai }
4730352f7f91STakashi Iwai 
4731dda42bd0STakashi Iwai /**
4732dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4733dda42bd0STakashi Iwai  * into power down
4734dda42bd0STakashi Iwai  * @codec: the HDA codec
4735dda42bd0STakashi Iwai  * @nid: NID to evalute
4736dda42bd0STakashi Iwai  * @power_state: target power state
4737dda42bd0STakashi Iwai  */
4738dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
473955196fffSTakashi Iwai 						  hda_nid_t nid,
474055196fffSTakashi Iwai 						  unsigned int power_state)
474155196fffSTakashi Iwai {
4742b6c09b3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4743b6c09b3cSTakashi Iwai 
4744b6c09b3cSTakashi Iwai 	if (!spec->power_down_unused && !codec->power_save_node)
4745b6c09b3cSTakashi Iwai 		return power_state;
47467639a06cSTakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
474755196fffSTakashi Iwai 		return power_state;
474855196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
474955196fffSTakashi Iwai 		return power_state;
4750b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
475155196fffSTakashi Iwai 		return power_state;
475255196fffSTakashi Iwai 	return AC_PWRST_D3;
475355196fffSTakashi Iwai }
4754dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
475555196fffSTakashi Iwai 
4756ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4757ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4758ebb93c05STakashi Iwai {
4759ebb93c05STakashi Iwai 	int i, nums;
4760ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4761ebb93c05STakashi Iwai 	bool has_amp;
4762ebb93c05STakashi Iwai 
4763ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4764ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4765ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4766ebb93c05STakashi Iwai 		if (has_amp)
4767ef403edbSTakashi Iwai 			update_amp(codec, mix, HDA_INPUT, i,
4768ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4769ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4770ef403edbSTakashi Iwai 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
4771ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4772ebb93c05STakashi Iwai 	}
4773ebb93c05STakashi Iwai }
4774352f7f91STakashi Iwai 
4775dda42bd0STakashi Iwai /**
4776e6feb5d0STakashi Iwai  * snd_hda_gen_stream_pm - Stream power management callback
4777e6feb5d0STakashi Iwai  * @codec: the HDA codec
4778e6feb5d0STakashi Iwai  * @nid: audio widget
4779e6feb5d0STakashi Iwai  * @on: power on/off flag
4780e6feb5d0STakashi Iwai  *
4781967b1307STakashi Iwai  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
4782e6feb5d0STakashi Iwai  */
4783e6feb5d0STakashi Iwai void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
4784e6feb5d0STakashi Iwai {
4785967b1307STakashi Iwai 	if (codec->power_save_node)
4786e6feb5d0STakashi Iwai 		set_path_power(codec, nid, -1, on);
4787e6feb5d0STakashi Iwai }
4788e6feb5d0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
4789e6feb5d0STakashi Iwai 
4790e6feb5d0STakashi Iwai /**
4791dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
4792dda42bd0STakashi Iwai  * set up the hda_gen_spec
4793dda42bd0STakashi Iwai  * @codec: the HDA codec
4794dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
47959eb413e5STakashi Iwai  *
47969eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4797352f7f91STakashi Iwai  * or a negative error code
4798352f7f91STakashi Iwai  */
4799352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
48009eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4801352f7f91STakashi Iwai {
4802352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4803352f7f91STakashi Iwai 	int err;
4804352f7f91STakashi Iwai 
48051c70a583STakashi Iwai 	parse_user_hints(codec);
48061c70a583STakashi Iwai 
4807e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4808e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4809e4a395e7STakashi Iwai 
48109eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
48119eb413e5STakashi Iwai 		spec->autocfg = *cfg;
48129eb413e5STakashi Iwai 		cfg = &spec->autocfg;
48139eb413e5STakashi Iwai 	}
48149eb413e5STakashi Iwai 
481598bd1115STakashi Iwai 	if (!spec->main_out_badness)
481698bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
481798bd1115STakashi Iwai 	if (!spec->extra_out_badness)
481898bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
481998bd1115STakashi Iwai 
48206fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
48216fc4cb97SDavid Henningsson 
4822352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4823352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4824352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4825352f7f91STakashi Iwai 			spec->no_analog = 1;
4826352f7f91STakashi Iwai 			goto dig_only;
4827352f7f91STakashi Iwai 		}
4828c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4829352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4830352f7f91STakashi Iwai 	}
4831352f7f91STakashi Iwai 
4832352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4833352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4834352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4835352f7f91STakashi Iwai 		/* use HP as primary out */
4836352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4837352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4838352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4839352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4840352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4841352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4842352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4843352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4844352f7f91STakashi Iwai 	}
4845352f7f91STakashi Iwai 
4846352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4847352f7f91STakashi Iwai 	if (err < 0)
4848352f7f91STakashi Iwai 		return err;
4849352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4850352f7f91STakashi Iwai 	if (err < 0)
4851352f7f91STakashi Iwai 		return err;
4852352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4853352f7f91STakashi Iwai 	if (err < 0)
4854352f7f91STakashi Iwai 		return err;
4855352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4856352f7f91STakashi Iwai 	if (err < 0)
4857352f7f91STakashi Iwai 		return err;
4858352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4859352f7f91STakashi Iwai 	if (err < 0)
4860352f7f91STakashi Iwai 		return err;
486138cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
486238cf6f1aSTakashi Iwai 	if (err < 0)
486338cf6f1aSTakashi Iwai 		return err;
4864c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4865c30aa7b2STakashi Iwai 	if (err < 0)
4866c30aa7b2STakashi Iwai 		return err;
4867967303daSTakashi Iwai 	err = create_hp_mic(codec);
4868352f7f91STakashi Iwai 	if (err < 0)
4869352f7f91STakashi Iwai 		return err;
4870352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4871352f7f91STakashi Iwai 	if (err < 0)
4872352f7f91STakashi Iwai 		return err;
4873352f7f91STakashi Iwai 
4874e6feb5d0STakashi Iwai 	/* add power-down pin callbacks at first */
4875e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, false);
4876e6feb5d0STakashi Iwai 
4877a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4878a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4879a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4880a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4881a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4882a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4883a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4884a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4885352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4886352f7f91STakashi Iwai 					  spec->const_channel_count);
4887352f7f91STakashi Iwai 
4888352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4889352f7f91STakashi Iwai 	if (err < 0)
4890352f7f91STakashi Iwai 		return err;
4891352f7f91STakashi Iwai 
4892352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4893352f7f91STakashi Iwai 	if (err < 0)
4894352f7f91STakashi Iwai 		return err;
4895352f7f91STakashi Iwai 
4896352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4897352f7f91STakashi Iwai 	if (err < 0)
4898352f7f91STakashi Iwai 		return err;
4899352f7f91STakashi Iwai 
4900f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
4901f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
490274f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
490374f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
4904f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
4905f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
4906f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
4907f1e762ddSTakashi Iwai 		if (err < 0)
4908f1e762ddSTakashi Iwai 			return err;
4909f1e762ddSTakashi Iwai 	}
4910f1e762ddSTakashi Iwai 
4911f1e762ddSTakashi Iwai 
4912352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4913352f7f91STakashi Iwai 	if (err < 0)
4914352f7f91STakashi Iwai 		return err;
4915352f7f91STakashi Iwai 
4916352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4917352f7f91STakashi Iwai 	if (err < 0)
4918352f7f91STakashi Iwai 		return err;
4919352f7f91STakashi Iwai 
4920ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4921ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4922ced4cefcSTakashi Iwai 	 */
4923ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4924ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4925ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4926ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4927ced4cefcSTakashi Iwai 		if (err < 0)
4928ced4cefcSTakashi Iwai 			return err;
4929ced4cefcSTakashi Iwai 	}
4930ced4cefcSTakashi Iwai 
4931f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4932978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4933978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4934978e77e7STakashi Iwai 						    cfg->line_out_pins);
4935978e77e7STakashi Iwai 			if (err < 0)
4936978e77e7STakashi Iwai 				return err;
4937978e77e7STakashi Iwai 		}
4938978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4939978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4940978e77e7STakashi Iwai 						    cfg->hp_pins);
4941978e77e7STakashi Iwai 			if (err < 0)
4942978e77e7STakashi Iwai 				return err;
4943978e77e7STakashi Iwai 		}
4944978e77e7STakashi Iwai 	}
4945978e77e7STakashi Iwai 
4946e6feb5d0STakashi Iwai 	/* add power-up pin callbacks at last */
4947e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, true);
4948e6feb5d0STakashi Iwai 
4949ebb93c05STakashi Iwai 	/* mute all aamix input initially */
4950ebb93c05STakashi Iwai 	if (spec->mixer_nid)
4951ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
4952ebb93c05STakashi Iwai 
4953352f7f91STakashi Iwai  dig_only:
4954352f7f91STakashi Iwai 	parse_digital(codec);
4955352f7f91STakashi Iwai 
495649fb1897STakashi Iwai 	if (spec->power_down_unused || codec->power_save_node) {
495724fef902STakashi Iwai 		if (!codec->power_filter)
495855196fffSTakashi Iwai 			codec->power_filter = snd_hda_gen_path_power_filter;
495949fb1897STakashi Iwai 		if (!codec->patch_ops.stream_pm)
496049fb1897STakashi Iwai 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
496149fb1897STakashi Iwai 	}
496255196fffSTakashi Iwai 
49637504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
49647504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
49657504b6cdSTakashi Iwai 		if (err < 0)
49667504b6cdSTakashi Iwai 			return err;
4967967b1307STakashi Iwai 		if (codec->beep && codec->power_save_node) {
49685ccf835cSTakashi Iwai 			err = add_fake_beep_paths(codec);
49695ccf835cSTakashi Iwai 			if (err < 0)
49705ccf835cSTakashi Iwai 				return err;
49715ccf835cSTakashi Iwai 			codec->beep->power_hook = beep_power_hook;
49725ccf835cSTakashi Iwai 		}
49737504b6cdSTakashi Iwai 	}
49747504b6cdSTakashi Iwai 
4975352f7f91STakashi Iwai 	return 1;
4976352f7f91STakashi Iwai }
49772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
4978352f7f91STakashi Iwai 
4979352f7f91STakashi Iwai 
4980352f7f91STakashi Iwai /*
4981352f7f91STakashi Iwai  * Build control elements
4982352f7f91STakashi Iwai  */
4983352f7f91STakashi Iwai 
4984352f7f91STakashi Iwai /* slave controls for virtual master */
4985352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4986352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4987352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4988352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4989ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4990ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
499103ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
4992352f7f91STakashi Iwai 	NULL,
4993352f7f91STakashi Iwai };
4994352f7f91STakashi Iwai 
4995dda42bd0STakashi Iwai /**
4996dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
4997dda42bd0STakashi Iwai  * @codec: the HDA codec
4998dda42bd0STakashi Iwai  *
4999dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
5000dda42bd0STakashi Iwai  */
5001352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
5002352f7f91STakashi Iwai {
5003352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5004352f7f91STakashi Iwai 	int err;
5005352f7f91STakashi Iwai 
500636502d02STakashi Iwai 	if (spec->kctls.used) {
5007352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5008352f7f91STakashi Iwai 		if (err < 0)
5009352f7f91STakashi Iwai 			return err;
501036502d02STakashi Iwai 	}
5011352f7f91STakashi Iwai 
5012352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
5013352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
5014352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5015352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5016bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
5017352f7f91STakashi Iwai 		if (err < 0)
5018352f7f91STakashi Iwai 			return err;
5019352f7f91STakashi Iwai 		if (!spec->no_analog) {
5020352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
5021352f7f91STakashi Iwai 							    &spec->multiout);
5022352f7f91STakashi Iwai 			if (err < 0)
5023352f7f91STakashi Iwai 				return err;
5024352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
5025352f7f91STakashi Iwai 		}
5026352f7f91STakashi Iwai 	}
5027352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
5028352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5029352f7f91STakashi Iwai 		if (err < 0)
5030352f7f91STakashi Iwai 			return err;
5031352f7f91STakashi Iwai 	}
5032352f7f91STakashi Iwai 
5033352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
5034352f7f91STakashi Iwai 	if (!spec->no_analog &&
5035352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5036352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
50377a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
5038352f7f91STakashi Iwai 					  "Playback Volume");
5039352f7f91STakashi Iwai 		if (err < 0)
5040352f7f91STakashi Iwai 			return err;
5041352f7f91STakashi Iwai 	}
5042352f7f91STakashi Iwai 	if (!spec->no_analog &&
5043352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5044352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
5045352f7f91STakashi Iwai 					    NULL, slave_pfxs,
5046352f7f91STakashi Iwai 					    "Playback Switch",
5047352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
5048352f7f91STakashi Iwai 		if (err < 0)
5049352f7f91STakashi Iwai 			return err;
5050b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
5051fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
5052fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
5053b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5054b63eae0aSTakashi Iwai 		}
5055352f7f91STakashi Iwai 	}
5056352f7f91STakashi Iwai 
5057352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
5058352f7f91STakashi Iwai 
5059352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5060352f7f91STakashi Iwai 	if (err < 0)
5061352f7f91STakashi Iwai 		return err;
5062352f7f91STakashi Iwai 
5063352f7f91STakashi Iwai 	return 0;
5064352f7f91STakashi Iwai }
50652698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5066352f7f91STakashi Iwai 
5067352f7f91STakashi Iwai 
5068352f7f91STakashi Iwai /*
5069352f7f91STakashi Iwai  * PCM definitions
5070352f7f91STakashi Iwai  */
5071352f7f91STakashi Iwai 
5072e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5073e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
5074e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
5075e6b85f3cSTakashi Iwai 				   int action)
5076e6b85f3cSTakashi Iwai {
5077e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5078e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
5079e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5080e6b85f3cSTakashi Iwai }
5081e6b85f3cSTakashi Iwai 
5082ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5083ac2e8736STakashi Iwai 				  struct hda_codec *codec,
5084ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
5085ac2e8736STakashi Iwai 				  int action)
5086ac2e8736STakashi Iwai {
5087ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5088ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
5089ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5090ac2e8736STakashi Iwai }
5091ac2e8736STakashi Iwai 
5092352f7f91STakashi Iwai /*
5093352f7f91STakashi Iwai  * Analog playback callbacks
5094352f7f91STakashi Iwai  */
5095352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5096352f7f91STakashi Iwai 			     struct hda_codec *codec,
5097352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
5098352f7f91STakashi Iwai {
5099352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
510038cf6f1aSTakashi Iwai 	int err;
510138cf6f1aSTakashi Iwai 
510238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
510338cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
510438cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
5105352f7f91STakashi Iwai 					     hinfo);
5106e6b85f3cSTakashi Iwai 	if (!err) {
510738cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5108e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5109e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
5110e6b85f3cSTakashi Iwai 	}
511138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
511238cf6f1aSTakashi Iwai 	return err;
5113352f7f91STakashi Iwai }
5114352f7f91STakashi Iwai 
5115352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
511697ec558aSTakashi Iwai 				struct hda_codec *codec,
511797ec558aSTakashi Iwai 				unsigned int stream_tag,
511897ec558aSTakashi Iwai 				unsigned int format,
511997ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
512097ec558aSTakashi Iwai {
5121352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5122e6b85f3cSTakashi Iwai 	int err;
5123e6b85f3cSTakashi Iwai 
5124e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5125352f7f91STakashi Iwai 					       stream_tag, format, substream);
5126e6b85f3cSTakashi Iwai 	if (!err)
5127e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5128e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
5129e6b85f3cSTakashi Iwai 	return err;
5130352f7f91STakashi Iwai }
513197ec558aSTakashi Iwai 
5132352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5133352f7f91STakashi Iwai 				struct hda_codec *codec,
5134352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
5135352f7f91STakashi Iwai {
5136352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5137e6b85f3cSTakashi Iwai 	int err;
5138e6b85f3cSTakashi Iwai 
5139e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5140e6b85f3cSTakashi Iwai 	if (!err)
5141e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5142e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
5143e6b85f3cSTakashi Iwai 	return err;
5144352f7f91STakashi Iwai }
5145352f7f91STakashi Iwai 
514638cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
514738cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
514838cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
514938cf6f1aSTakashi Iwai {
515038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
515138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
515238cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5153e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5154e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
515538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
515638cf6f1aSTakashi Iwai 	return 0;
515738cf6f1aSTakashi Iwai }
515838cf6f1aSTakashi Iwai 
5159ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5160ac2e8736STakashi Iwai 			    struct hda_codec *codec,
5161ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
5162ac2e8736STakashi Iwai {
5163ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5164ac2e8736STakashi Iwai 	return 0;
5165ac2e8736STakashi Iwai }
5166ac2e8736STakashi Iwai 
5167ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5168ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5169ac2e8736STakashi Iwai 			       unsigned int stream_tag,
5170ac2e8736STakashi Iwai 			       unsigned int format,
5171ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5172ac2e8736STakashi Iwai {
5173ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5174ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5175ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
5176ac2e8736STakashi Iwai 	return 0;
5177ac2e8736STakashi Iwai }
5178ac2e8736STakashi Iwai 
5179ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5180ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5181ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5182ac2e8736STakashi Iwai {
5183ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5184ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5185ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
5186ac2e8736STakashi Iwai 	return 0;
5187ac2e8736STakashi Iwai }
5188ac2e8736STakashi Iwai 
5189ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5190ac2e8736STakashi Iwai 			     struct hda_codec *codec,
5191ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
5192ac2e8736STakashi Iwai {
5193ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5194ac2e8736STakashi Iwai 	return 0;
5195ac2e8736STakashi Iwai }
5196ac2e8736STakashi Iwai 
519738cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
519838cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
519938cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
520038cf6f1aSTakashi Iwai {
520138cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
520238cf6f1aSTakashi Iwai 	int err = 0;
520338cf6f1aSTakashi Iwai 
520438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
5205d1f15e06STakashi Iwai 	if (spec->indep_hp && !spec->indep_hp_enabled)
520638cf6f1aSTakashi Iwai 		err = -EBUSY;
520738cf6f1aSTakashi Iwai 	else
520838cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5209e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5210e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
521138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
521238cf6f1aSTakashi Iwai 	return err;
521338cf6f1aSTakashi Iwai }
521438cf6f1aSTakashi Iwai 
521538cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
521638cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
521738cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
521838cf6f1aSTakashi Iwai {
521938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
522038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
522138cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5222e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5223e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
522438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
522538cf6f1aSTakashi Iwai 	return 0;
522638cf6f1aSTakashi Iwai }
522738cf6f1aSTakashi Iwai 
5228e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5229e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5230e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
5231e6b85f3cSTakashi Iwai 				    unsigned int format,
5232e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5233e6b85f3cSTakashi Iwai {
5234e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5235e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5236e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
5237e6b85f3cSTakashi Iwai 	return 0;
5238e6b85f3cSTakashi Iwai }
5239e6b85f3cSTakashi Iwai 
5240e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5241e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5242e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5243e6b85f3cSTakashi Iwai {
5244e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5245e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5246e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
5247e6b85f3cSTakashi Iwai 	return 0;
5248e6b85f3cSTakashi Iwai }
5249e6b85f3cSTakashi Iwai 
5250352f7f91STakashi Iwai /*
5251352f7f91STakashi Iwai  * Digital out
5252352f7f91STakashi Iwai  */
5253352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5254352f7f91STakashi Iwai 				 struct hda_codec *codec,
5255352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
5256352f7f91STakashi Iwai {
5257352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5258352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5259352f7f91STakashi Iwai }
5260352f7f91STakashi Iwai 
5261352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5262352f7f91STakashi Iwai 				    struct hda_codec *codec,
5263352f7f91STakashi Iwai 				    unsigned int stream_tag,
5264352f7f91STakashi Iwai 				    unsigned int format,
5265352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5266352f7f91STakashi Iwai {
5267352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5268352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5269352f7f91STakashi Iwai 					     stream_tag, format, substream);
5270352f7f91STakashi Iwai }
5271352f7f91STakashi Iwai 
5272352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5273352f7f91STakashi Iwai 				    struct hda_codec *codec,
5274352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5275352f7f91STakashi Iwai {
5276352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5277352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5278352f7f91STakashi Iwai }
5279352f7f91STakashi Iwai 
5280352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5281352f7f91STakashi Iwai 				  struct hda_codec *codec,
5282352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
5283352f7f91STakashi Iwai {
5284352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5285352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5286352f7f91STakashi Iwai }
5287352f7f91STakashi Iwai 
5288352f7f91STakashi Iwai /*
5289352f7f91STakashi Iwai  * Analog capture
5290352f7f91STakashi Iwai  */
5291ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
5292ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
5293ac2e8736STakashi Iwai 
5294352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5295352f7f91STakashi Iwai 				   struct hda_codec *codec,
5296352f7f91STakashi Iwai 				   unsigned int stream_tag,
5297352f7f91STakashi Iwai 				   unsigned int format,
5298352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
5299352f7f91STakashi Iwai {
5300352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5301352f7f91STakashi Iwai 
5302352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
530397ec558aSTakashi Iwai 				   stream_tag, 0, format);
5304ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5305ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
530697ec558aSTakashi Iwai 	return 0;
530797ec558aSTakashi Iwai }
530897ec558aSTakashi Iwai 
5309352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
531097ec558aSTakashi Iwai 				   struct hda_codec *codec,
531197ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
531297ec558aSTakashi Iwai {
5313352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
531497ec558aSTakashi Iwai 
5315352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
5316352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
5317ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5318ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
531997ec558aSTakashi Iwai 	return 0;
532097ec558aSTakashi Iwai }
532197ec558aSTakashi Iwai 
5322352f7f91STakashi Iwai /*
5323352f7f91STakashi Iwai  */
5324352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
5325352f7f91STakashi Iwai 	.substreams = 1,
5326352f7f91STakashi Iwai 	.channels_min = 2,
5327352f7f91STakashi Iwai 	.channels_max = 8,
5328352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5329352f7f91STakashi Iwai 	.ops = {
5330352f7f91STakashi Iwai 		.open = playback_pcm_open,
533138cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
5332352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
5333352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
5334352f7f91STakashi Iwai 	},
5335352f7f91STakashi Iwai };
5336352f7f91STakashi Iwai 
5337352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
5338352f7f91STakashi Iwai 	.substreams = 1,
5339352f7f91STakashi Iwai 	.channels_min = 2,
5340352f7f91STakashi Iwai 	.channels_max = 2,
5341352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5342ac2e8736STakashi Iwai 	.ops = {
5343ac2e8736STakashi Iwai 		.open = capture_pcm_open,
5344ac2e8736STakashi Iwai 		.close = capture_pcm_close,
5345ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
5346ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
5347ac2e8736STakashi Iwai 	},
5348352f7f91STakashi Iwai };
5349352f7f91STakashi Iwai 
5350352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
5351352f7f91STakashi Iwai 	.substreams = 1,
5352352f7f91STakashi Iwai 	.channels_min = 2,
5353352f7f91STakashi Iwai 	.channels_max = 2,
5354352f7f91STakashi Iwai 	/* NID is set in build_pcms */
535538cf6f1aSTakashi Iwai 	.ops = {
535638cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
5357e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
5358e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
5359e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
536038cf6f1aSTakashi Iwai 	},
5361352f7f91STakashi Iwai };
5362352f7f91STakashi Iwai 
5363352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
5364352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
5365352f7f91STakashi Iwai 	.channels_min = 2,
5366352f7f91STakashi Iwai 	.channels_max = 2,
5367352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5368352f7f91STakashi Iwai 	.ops = {
5369ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5370ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5371352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5372352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5373352f7f91STakashi Iwai 	},
5374352f7f91STakashi Iwai };
5375352f7f91STakashi Iwai 
5376352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5377352f7f91STakashi Iwai 	.substreams = 1,
5378352f7f91STakashi Iwai 	.channels_min = 2,
5379352f7f91STakashi Iwai 	.channels_max = 2,
5380352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5381352f7f91STakashi Iwai 	.ops = {
5382352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5383352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5384352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5385352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5386352f7f91STakashi Iwai 	},
5387352f7f91STakashi Iwai };
5388352f7f91STakashi Iwai 
5389352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5390352f7f91STakashi Iwai 	.substreams = 1,
5391352f7f91STakashi Iwai 	.channels_min = 2,
5392352f7f91STakashi Iwai 	.channels_max = 2,
5393352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5394352f7f91STakashi Iwai };
5395352f7f91STakashi Iwai 
5396352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5397352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5398352f7f91STakashi Iwai 	.substreams = 0,
5399352f7f91STakashi Iwai 	.channels_min = 0,
5400352f7f91STakashi Iwai 	.channels_max = 0,
5401352f7f91STakashi Iwai };
5402352f7f91STakashi Iwai 
5403352f7f91STakashi Iwai /*
5404352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5405352f7f91STakashi Iwai  */
5406352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
54071da177e4SLinus Torvalds {
5408352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5409352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
54101da177e4SLinus Torvalds 
5411352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5412352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5413352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5414352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5415352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5416352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5417352f7f91STakashi Iwai 					   spec->cur_adc_format);
5418352f7f91STakashi Iwai 		return true;
5419352f7f91STakashi Iwai 	}
5420352f7f91STakashi Iwai 	return false;
5421352f7f91STakashi Iwai }
5422352f7f91STakashi Iwai 
5423352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5424352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5425352f7f91STakashi Iwai 				       struct hda_codec *codec,
5426352f7f91STakashi Iwai 				       unsigned int stream_tag,
5427352f7f91STakashi Iwai 				       unsigned int format,
5428352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5429352f7f91STakashi Iwai {
5430352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5431352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5432352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5433352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5434352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
54351da177e4SLinus Torvalds 	return 0;
54361da177e4SLinus Torvalds }
54371da177e4SLinus Torvalds 
5438352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5439352f7f91STakashi Iwai 				       struct hda_codec *codec,
5440352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5441352f7f91STakashi Iwai {
5442352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5443352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5444352f7f91STakashi Iwai 	spec->cur_adc = 0;
5445352f7f91STakashi Iwai 	return 0;
5446352f7f91STakashi Iwai }
5447352f7f91STakashi Iwai 
5448352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5449352f7f91STakashi Iwai 	.substreams = 1,
5450352f7f91STakashi Iwai 	.channels_min = 2,
5451352f7f91STakashi Iwai 	.channels_max = 2,
5452352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5453352f7f91STakashi Iwai 	.ops = {
5454352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5455352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5456352f7f91STakashi Iwai 	},
5457352f7f91STakashi Iwai };
5458352f7f91STakashi Iwai 
5459f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5460f873e536STakashi Iwai 				 const char *chip_name)
5461f873e536STakashi Iwai {
5462f873e536STakashi Iwai 	char *p;
5463f873e536STakashi Iwai 
5464f873e536STakashi Iwai 	if (*str)
5465f873e536STakashi Iwai 		return;
5466f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
5467f873e536STakashi Iwai 
5468f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5469f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5470f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5471f873e536STakashi Iwai 			*p = 0;
5472f873e536STakashi Iwai 			break;
5473f873e536STakashi Iwai 		}
5474f873e536STakashi Iwai 	}
5475f873e536STakashi Iwai 	strlcat(str, sfx, len);
5476f873e536STakashi Iwai }
5477f873e536STakashi Iwai 
5478fb83b635STakashi Iwai /* copy PCM stream info from @default_str, and override non-NULL entries
5479fb83b635STakashi Iwai  * from @spec_str and @nid
5480fb83b635STakashi Iwai  */
5481fb83b635STakashi Iwai static void setup_pcm_stream(struct hda_pcm_stream *str,
5482fb83b635STakashi Iwai 			     const struct hda_pcm_stream *default_str,
5483fb83b635STakashi Iwai 			     const struct hda_pcm_stream *spec_str,
5484fb83b635STakashi Iwai 			     hda_nid_t nid)
5485fb83b635STakashi Iwai {
5486fb83b635STakashi Iwai 	*str = *default_str;
5487fb83b635STakashi Iwai 	if (nid)
5488fb83b635STakashi Iwai 		str->nid = nid;
5489fb83b635STakashi Iwai 	if (spec_str) {
5490fb83b635STakashi Iwai 		if (spec_str->substreams)
5491fb83b635STakashi Iwai 			str->substreams = spec_str->substreams;
5492fb83b635STakashi Iwai 		if (spec_str->channels_min)
5493fb83b635STakashi Iwai 			str->channels_min = spec_str->channels_min;
5494fb83b635STakashi Iwai 		if (spec_str->channels_max)
5495fb83b635STakashi Iwai 			str->channels_max = spec_str->channels_max;
5496fb83b635STakashi Iwai 		if (spec_str->rates)
5497fb83b635STakashi Iwai 			str->rates = spec_str->rates;
5498fb83b635STakashi Iwai 		if (spec_str->formats)
5499fb83b635STakashi Iwai 			str->formats = spec_str->formats;
5500fb83b635STakashi Iwai 		if (spec_str->maxbps)
5501fb83b635STakashi Iwai 			str->maxbps = spec_str->maxbps;
5502fb83b635STakashi Iwai 	}
5503fb83b635STakashi Iwai }
5504fb83b635STakashi Iwai 
5505dda42bd0STakashi Iwai /**
5506dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5507dda42bd0STakashi Iwai  * @codec: the HDA codec
5508dda42bd0STakashi Iwai  *
5509dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5510dda42bd0STakashi Iwai  */
5511352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5512352f7f91STakashi Iwai {
5513352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5514bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5515352f7f91STakashi Iwai 	bool have_multi_adcs;
5516352f7f91STakashi Iwai 
5517352f7f91STakashi Iwai 	if (spec->no_analog)
5518352f7f91STakashi Iwai 		goto skip_analog;
5519352f7f91STakashi Iwai 
5520f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5521f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
55227639a06cSTakashi Iwai 			     " Analog", codec->core.chip_name);
5523bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5524bbbc7e85STakashi Iwai 	if (!info)
5525bbbc7e85STakashi Iwai 		return -ENOMEM;
5526bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5527352f7f91STakashi Iwai 
5528352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5529fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5530fb83b635STakashi Iwai 				 &pcm_analog_playback,
5531fb83b635STakashi Iwai 				 spec->stream_analog_playback,
5532fb83b635STakashi Iwai 				 spec->multiout.dac_nids[0]);
5533352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5534352f7f91STakashi Iwai 			spec->multiout.max_channels;
5535352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5536352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5537352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5538352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5539352f7f91STakashi Iwai 	}
5540352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5541fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5542fb83b635STakashi Iwai 				 (spec->dyn_adc_switch ?
5543fb83b635STakashi Iwai 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5544fb83b635STakashi Iwai 				 spec->stream_analog_capture,
5545fb83b635STakashi Iwai 				 spec->adc_nids[0]);
5546352f7f91STakashi Iwai 	}
5547352f7f91STakashi Iwai 
5548352f7f91STakashi Iwai  skip_analog:
5549352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5550352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5551f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5552352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
55537639a06cSTakashi Iwai 				     " Digital", codec->core.chip_name);
5554bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5555bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5556bbbc7e85STakashi Iwai 		if (!info)
5557bbbc7e85STakashi Iwai 			return -ENOMEM;
5558352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5559bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5560352f7f91STakashi Iwai 		if (spec->dig_out_type)
5561352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5562352f7f91STakashi Iwai 		else
5563352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5564fb83b635STakashi Iwai 		if (spec->multiout.dig_out_nid)
5565fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5566fb83b635STakashi Iwai 					 &pcm_digital_playback,
5567fb83b635STakashi Iwai 					 spec->stream_digital_playback,
5568fb83b635STakashi Iwai 					 spec->multiout.dig_out_nid);
5569fb83b635STakashi Iwai 		if (spec->dig_in_nid)
5570fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5571fb83b635STakashi Iwai 					 &pcm_digital_capture,
5572fb83b635STakashi Iwai 					 spec->stream_digital_capture,
5573fb83b635STakashi Iwai 					 spec->dig_in_nid);
5574352f7f91STakashi Iwai 	}
5575352f7f91STakashi Iwai 
5576352f7f91STakashi Iwai 	if (spec->no_analog)
5577352f7f91STakashi Iwai 		return 0;
5578352f7f91STakashi Iwai 
5579352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5580352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5581352f7f91STakashi Iwai 	 */
5582352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5583352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5584352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5585352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5586a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5587a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
55887639a06cSTakashi Iwai 			     " Alt Analog", codec->core.chip_name);
5589bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5590bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5591bbbc7e85STakashi Iwai 		if (!info)
5592bbbc7e85STakashi Iwai 			return -ENOMEM;
5593bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5594fb83b635STakashi Iwai 		if (spec->alt_dac_nid)
5595fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5596fb83b635STakashi Iwai 					 &pcm_analog_alt_playback,
5597fb83b635STakashi Iwai 					 spec->stream_analog_alt_playback,
5598fb83b635STakashi Iwai 					 spec->alt_dac_nid);
5599fb83b635STakashi Iwai 		else
5600fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5601fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5602352f7f91STakashi Iwai 		if (have_multi_adcs) {
5603fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5604fb83b635STakashi Iwai 					 &pcm_analog_alt_capture,
5605fb83b635STakashi Iwai 					 spec->stream_analog_alt_capture,
5606fb83b635STakashi Iwai 					 spec->adc_nids[1]);
5607352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5608352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5609352f7f91STakashi Iwai 		} else {
5610fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5611fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5612352f7f91STakashi Iwai 		}
56131da177e4SLinus Torvalds 	}
56141da177e4SLinus Torvalds 
56151da177e4SLinus Torvalds 	return 0;
56161da177e4SLinus Torvalds }
56172698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5618352f7f91STakashi Iwai 
5619352f7f91STakashi Iwai 
5620352f7f91STakashi Iwai /*
5621352f7f91STakashi Iwai  * Standard auto-parser initializations
5622352f7f91STakashi Iwai  */
5623352f7f91STakashi Iwai 
5624d4156930STakashi Iwai /* configure the given path as a proper output */
56252c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5626352f7f91STakashi Iwai {
5627352f7f91STakashi Iwai 	struct nid_path *path;
5628d4156930STakashi Iwai 	hda_nid_t pin;
5629352f7f91STakashi Iwai 
5630196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5631d4156930STakashi Iwai 	if (!path || !path->depth)
5632352f7f91STakashi Iwai 		return;
5633d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
56342c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
563565033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
563665033cc8STakashi Iwai 			      aamix_default(codec->spec));
5637e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5638352f7f91STakashi Iwai }
5639352f7f91STakashi Iwai 
5640352f7f91STakashi Iwai /* initialize primary output paths */
5641352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5642352f7f91STakashi Iwai {
5643352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5644352f7f91STakashi Iwai 	int i;
5645352f7f91STakashi Iwai 
5646d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
56472c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5648352f7f91STakashi Iwai }
5649352f7f91STakashi Iwai 
5650db23fd19STakashi Iwai 
56512c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5652352f7f91STakashi Iwai {
5653352f7f91STakashi Iwai 	int i;
5654352f7f91STakashi Iwai 
5655d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
56562c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5657352f7f91STakashi Iwai }
5658db23fd19STakashi Iwai 
5659db23fd19STakashi Iwai /* initialize hp and speaker paths */
5660db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5661db23fd19STakashi Iwai {
5662db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5663db23fd19STakashi Iwai 
5664db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
56652c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5666db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5667db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
56682c12c30dSTakashi Iwai 				 spec->speaker_paths);
5669352f7f91STakashi Iwai }
5670352f7f91STakashi Iwai 
5671352f7f91STakashi Iwai /* initialize multi-io paths */
5672352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5673352f7f91STakashi Iwai {
5674352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5675352f7f91STakashi Iwai 	int i;
5676352f7f91STakashi Iwai 
5677352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5678352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5679352f7f91STakashi Iwai 		struct nid_path *path;
5680196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5681352f7f91STakashi Iwai 		if (!path)
5682352f7f91STakashi Iwai 			continue;
5683352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5684352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
56852c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
568665033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
568765033cc8STakashi Iwai 				      aamix_default(spec));
5688352f7f91STakashi Iwai 	}
5689352f7f91STakashi Iwai }
5690352f7f91STakashi Iwai 
56914f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
56924f7f67fbSTakashi Iwai {
56934f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
56944f7f67fbSTakashi Iwai 
56954f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
56964f7f67fbSTakashi Iwai 		return;
5697e7fdd527STakashi Iwai 	if (!has_aamix_out_paths(spec))
5698e7fdd527STakashi Iwai 		return;
56994f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
57004f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
57014f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
57024f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
57034f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
57044f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
57054f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
57064f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
57074f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
57084f7f67fbSTakashi Iwai }
57094f7f67fbSTakashi Iwai 
5710352f7f91STakashi Iwai /* set up input pins and loopback paths */
5711352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5712352f7f91STakashi Iwai {
5713352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5714352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5715352f7f91STakashi Iwai 	int i;
5716352f7f91STakashi Iwai 
5717352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5718352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5719352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
57202c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5721352f7f91STakashi Iwai 
5722352f7f91STakashi Iwai 		/* init loopback inputs */
5723352f7f91STakashi Iwai 		if (spec->mixer_nid) {
57243e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
57253e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5726352f7f91STakashi Iwai 		}
5727352f7f91STakashi Iwai 	}
5728352f7f91STakashi Iwai }
5729352f7f91STakashi Iwai 
5730352f7f91STakashi Iwai /* initialize ADC paths */
5731352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5732352f7f91STakashi Iwai {
5733352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5734352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5735352f7f91STakashi Iwai 	struct nid_path *path;
5736352f7f91STakashi Iwai 	int i, c, nums;
5737352f7f91STakashi Iwai 
5738352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5739352f7f91STakashi Iwai 		nums = 1;
5740352f7f91STakashi Iwai 	else
5741352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5742352f7f91STakashi Iwai 
5743352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5744352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5745c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5746352f7f91STakashi Iwai 			if (path) {
5747352f7f91STakashi Iwai 				bool active = path->active;
5748352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5749352f7f91STakashi Iwai 					active = true;
5750352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5751352f7f91STakashi Iwai 			}
5752352f7f91STakashi Iwai 		}
5753967303daSTakashi Iwai 		if (spec->hp_mic)
5754967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5755352f7f91STakashi Iwai 	}
5756352f7f91STakashi Iwai 
5757352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
57587fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
5759352f7f91STakashi Iwai }
5760352f7f91STakashi Iwai 
5761352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5762352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5763352f7f91STakashi Iwai {
5764352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5765352f7f91STakashi Iwai 	int i;
5766352f7f91STakashi Iwai 	hda_nid_t pin;
5767352f7f91STakashi Iwai 
5768d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
57692c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5770352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
57712430d7b7STakashi Iwai 	if (pin) {
57722c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
57733e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
57742430d7b7STakashi Iwai 	}
5775352f7f91STakashi Iwai }
5776352f7f91STakashi Iwai 
5777973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5778973e4972STakashi Iwai  * invalid unsol tags by some reason
5779973e4972STakashi Iwai  */
5780973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5781973e4972STakashi Iwai {
5782973e4972STakashi Iwai 	int i;
5783973e4972STakashi Iwai 
5784973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5785973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5786973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5787973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5788973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5789973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5790973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5791973e4972STakashi Iwai 	}
5792973e4972STakashi Iwai }
5793973e4972STakashi Iwai 
5794dda42bd0STakashi Iwai /**
5795dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
5796dda42bd0STakashi Iwai  * @codec: the HDA codec
5797dda42bd0STakashi Iwai  *
5798dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
57995187ac16STakashi Iwai  */
5800352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5801352f7f91STakashi Iwai {
5802352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5803352f7f91STakashi Iwai 
5804352f7f91STakashi Iwai 	if (spec->init_hook)
5805352f7f91STakashi Iwai 		spec->init_hook(codec);
5806352f7f91STakashi Iwai 
5807352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5808352f7f91STakashi Iwai 
5809352f7f91STakashi Iwai 	init_multi_out(codec);
5810352f7f91STakashi Iwai 	init_extra_out(codec);
5811352f7f91STakashi Iwai 	init_multi_io(codec);
58124f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5813352f7f91STakashi Iwai 	init_analog_input(codec);
5814352f7f91STakashi Iwai 	init_input_src(codec);
5815352f7f91STakashi Iwai 	init_digital(codec);
5816352f7f91STakashi Iwai 
5817973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5818973e4972STakashi Iwai 
5819e6feb5d0STakashi Iwai 	sync_all_pin_power_ctls(codec);
5820e6feb5d0STakashi Iwai 
5821352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5822a5cc2509STakashi Iwai 	update_automute_all(codec);
5823352f7f91STakashi Iwai 
5824a551d914STakashi Iwai 	regcache_sync(codec->core.regmap);
58253bbcd274STakashi Iwai 
5826352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5827352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5828352f7f91STakashi Iwai 
5829352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5830352f7f91STakashi Iwai 	return 0;
5831352f7f91STakashi Iwai }
58322698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5833fce52a3bSTakashi Iwai 
5834dda42bd0STakashi Iwai /**
5835dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
5836dda42bd0STakashi Iwai  * @codec: the HDA codec
5837dda42bd0STakashi Iwai  *
5838dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
58395187ac16STakashi Iwai  */
5840fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5841fce52a3bSTakashi Iwai {
58428a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
5843fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5844fce52a3bSTakashi Iwai 	kfree(codec->spec);
5845fce52a3bSTakashi Iwai 	codec->spec = NULL;
5846fce52a3bSTakashi Iwai }
58472698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
5848fce52a3bSTakashi Iwai 
5849fce52a3bSTakashi Iwai #ifdef CONFIG_PM
5850dda42bd0STakashi Iwai /**
5851dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
5852dda42bd0STakashi Iwai  * @codec: the HDA codec
5853dda42bd0STakashi Iwai  * @nid: NID to inspect
5854dda42bd0STakashi Iwai  *
5855dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
58565187ac16STakashi Iwai  */
5857fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5858fce52a3bSTakashi Iwai {
5859fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5860fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5861fce52a3bSTakashi Iwai }
58622698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
5863fce52a3bSTakashi Iwai #endif
5864352f7f91STakashi Iwai 
5865352f7f91STakashi Iwai 
5866352f7f91STakashi Iwai /*
5867352f7f91STakashi Iwai  * the generic codec support
5868352f7f91STakashi Iwai  */
58691da177e4SLinus Torvalds 
5870352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5871352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5872352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5873352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5874fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5875352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
587683012a7cSTakashi Iwai #ifdef CONFIG_PM
5877fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5878cb53c626STakashi Iwai #endif
58791da177e4SLinus Torvalds };
58801da177e4SLinus Torvalds 
5881d8a766a1STakashi Iwai /*
5882dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
5883dda42bd0STakashi Iwai  * @codec: the HDA codec
5884dda42bd0STakashi Iwai  */
5885d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
58861da177e4SLinus Torvalds {
5887352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
58881da177e4SLinus Torvalds 	int err;
58891da177e4SLinus Torvalds 
5890e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5891352f7f91STakashi Iwai 	if (!spec)
58921da177e4SLinus Torvalds 		return -ENOMEM;
5893352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
58941da177e4SLinus Torvalds 	codec->spec = spec;
58951da177e4SLinus Torvalds 
58969eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
58979eb413e5STakashi Iwai 	if (err < 0)
58989eb413e5STakashi Iwai 		return err;
58999eb413e5STakashi Iwai 
59009eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5901352f7f91STakashi Iwai 	if (err < 0)
59021da177e4SLinus Torvalds 		goto error;
59031da177e4SLinus Torvalds 
59041da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
59051da177e4SLinus Torvalds 	return 0;
59061da177e4SLinus Torvalds 
59071da177e4SLinus Torvalds error:
5908fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
59091da177e4SLinus Torvalds 	return err;
59101da177e4SLinus Torvalds }
5911d8a766a1STakashi Iwai 
5912b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_generic[] = {
5913b9a94a9cSTakashi Iwai 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
5914d8a766a1STakashi Iwai 	{} /* terminator */
5915d8a766a1STakashi Iwai };
5916b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
5917d8a766a1STakashi Iwai 
5918d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
5919b9a94a9cSTakashi Iwai 	.id = snd_hda_id_generic,
5920d8a766a1STakashi Iwai };
5921d8a766a1STakashi Iwai 
5922d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
5923b21bdd0dSTakashi Iwai 
5924b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
5925b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
5926