xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision bbbc7e85)
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;
1431c70a583STakashi Iwai 
144f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
145f72706beSTakashi Iwai 	if (val >= 0)
146f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1471c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1481c70a583STakashi Iwai 	if (val >= 0)
1491c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1537eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1547eebffd3STakashi Iwai 	if (val >= 0)
1557eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1561c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1571c70a583STakashi Iwai 	if (val >= 0)
1581c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1591c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1601c70a583STakashi Iwai 	if (val >= 0)
1611c70a583STakashi Iwai 		spec->no_primary_hp = !val;
162da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
163da96fb5bSTakashi Iwai 	if (val >= 0)
164da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1651c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1661c70a583STakashi Iwai 	if (val >= 0)
1671c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1681c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1691c70a583STakashi Iwai 	if (val >= 0)
1701c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1711c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1721c70a583STakashi Iwai 	if (val >= 0)
1731c70a583STakashi Iwai 		spec->indep_hp = !!val;
1741c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1751c70a583STakashi Iwai 	if (val >= 0)
1761c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
177f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1781c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1791c70a583STakashi Iwai 	if (val >= 0)
180f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
18129476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
18229476558STakashi Iwai 	if (val >= 0)
183f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
184f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
185f811c3cfSTakashi Iwai 	if (val >= 0)
186f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
18755196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
18855196fffSTakashi Iwai 	if (val >= 0)
18955196fffSTakashi Iwai 		spec->power_down_unused = !!val;
190967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
191967303daSTakashi Iwai 	if (val >= 0)
192967303daSTakashi Iwai 		spec->hp_mic = !!val;
193967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
194967303daSTakashi Iwai 	if (val >= 0)
195967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1961c70a583STakashi Iwai 
1971c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1981c70a583STakashi Iwai 		spec->mixer_nid = val;
1991c70a583STakashi Iwai }
2001c70a583STakashi Iwai 
2011c70a583STakashi Iwai /*
2022c12c30dSTakashi Iwai  * pin control value accesses
2032c12c30dSTakashi Iwai  */
2042c12c30dSTakashi Iwai 
2052c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
2062c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
2072c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
2082c12c30dSTakashi Iwai 
2092c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
2102c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
2112c12c30dSTakashi Iwai {
2122c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
2132c12c30dSTakashi Iwai }
2142c12c30dSTakashi Iwai 
2152c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2162c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2172c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2182c12c30dSTakashi Iwai {
2192c12c30dSTakashi Iwai 	if (!pin)
2202c12c30dSTakashi Iwai 		return;
2212c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2222c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2232c12c30dSTakashi Iwai 	if (do_write)
2242c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2252c12c30dSTakashi Iwai }
2262c12c30dSTakashi Iwai 
2272c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2282c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2292c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2302c12c30dSTakashi Iwai {
2312c12c30dSTakashi Iwai 	int i;
2322c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2332c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2342c12c30dSTakashi Iwai }
2352c12c30dSTakashi Iwai 
2362c12c30dSTakashi Iwai /*
237352f7f91STakashi Iwai  * parsing paths
2381da177e4SLinus Torvalds  */
2391da177e4SLinus Torvalds 
2403ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2413ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2423ca529d3STakashi Iwai {
2433ca529d3STakashi Iwai 	int i;
2443ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2453ca529d3STakashi Iwai 		if (list[i] == nid)
2463ca529d3STakashi Iwai 			return i;
2473ca529d3STakashi Iwai 	return -1;
2483ca529d3STakashi Iwai }
2493ca529d3STakashi Iwai 
2503ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2513ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2523ca529d3STakashi Iwai {
2533ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2543ca529d3STakashi Iwai }
2553ca529d3STakashi Iwai 
256f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
257f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2583ca529d3STakashi Iwai 				     int anchor_nid)
2591da177e4SLinus Torvalds {
260352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
261352f7f91STakashi Iwai 	int i;
2621da177e4SLinus Torvalds 
263352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
264352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
265352f7f91STakashi Iwai 		if (path->depth <= 0)
266352f7f91STakashi Iwai 			continue;
267352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
268f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2693ca529d3STakashi Iwai 			if (!anchor_nid ||
2703ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2713ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
272352f7f91STakashi Iwai 				return path;
2731da177e4SLinus Torvalds 		}
274f5172a7eSTakashi Iwai 	}
2751da177e4SLinus Torvalds 	return NULL;
2761da177e4SLinus Torvalds }
277f5172a7eSTakashi Iwai 
278dda42bd0STakashi Iwai /**
279dda42bd0STakashi Iwai  * snd_hda_get_nid_path - get the path between the given NIDs
280dda42bd0STakashi Iwai  * @codec: the HDA codec
281dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
282dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
283dda42bd0STakashi Iwai  *
284dda42bd0STakashi Iwai  * Return the found nid_path object or NULL for error.
285dda42bd0STakashi Iwai  * Passing 0 to either @from_nid or @to_nid behaves as a wildcard.
286f5172a7eSTakashi Iwai  */
287f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
288f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
289f5172a7eSTakashi Iwai {
2903ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
291f5172a7eSTakashi Iwai }
2922698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_nid_path);
2931da177e4SLinus Torvalds 
294dda42bd0STakashi Iwai /**
295dda42bd0STakashi Iwai  * snd_hda_get_path_idx - get the index number corresponding to the path
296dda42bd0STakashi Iwai  * instance
297dda42bd0STakashi Iwai  * @codec: the HDA codec
298dda42bd0STakashi Iwai  * @path: nid_path object
299dda42bd0STakashi Iwai  *
300dda42bd0STakashi Iwai  * The returned index starts from 1, i.e. the actual array index with offset 1,
301dda42bd0STakashi Iwai  * and zero is handled as an invalid path
302196c1766STakashi Iwai  */
303196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
304196c1766STakashi Iwai {
305196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
306196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
307196c1766STakashi Iwai 	ssize_t idx;
308196c1766STakashi Iwai 
309196c1766STakashi Iwai 	if (!spec->paths.used)
310196c1766STakashi Iwai 		return 0;
311196c1766STakashi Iwai 	idx = path - array;
312196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
313196c1766STakashi Iwai 		return 0;
314196c1766STakashi Iwai 	return idx + 1;
315196c1766STakashi Iwai }
3162698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
317196c1766STakashi Iwai 
318dda42bd0STakashi Iwai /**
319dda42bd0STakashi Iwai  * snd_hda_get_path_from_idx - get the path instance corresponding to the
320dda42bd0STakashi Iwai  * given index number
321dda42bd0STakashi Iwai  * @codec: the HDA codec
322dda42bd0STakashi Iwai  * @idx: the path index
323dda42bd0STakashi Iwai  */
324196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
325196c1766STakashi Iwai {
326196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
327196c1766STakashi Iwai 
328196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
329196c1766STakashi Iwai 		return NULL;
330196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
331196c1766STakashi Iwai }
3322698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
333196c1766STakashi Iwai 
334352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
335352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3361da177e4SLinus Torvalds {
337352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
338352f7f91STakashi Iwai 	int i;
339352f7f91STakashi Iwai 
340352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
341352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
342352f7f91STakashi Iwai 		if (path->path[0] == nid)
343352f7f91STakashi Iwai 			return true;
344352f7f91STakashi Iwai 	}
345352f7f91STakashi Iwai 	return false;
3461da177e4SLinus Torvalds }
3471da177e4SLinus Torvalds 
348352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
349352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
350352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3511da177e4SLinus Torvalds {
352352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
353352f7f91STakashi Iwai 		return false;
354352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3551da177e4SLinus Torvalds }
3561da177e4SLinus Torvalds 
357352f7f91STakashi Iwai /* nid, dir and idx */
358352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
359352f7f91STakashi Iwai 
360352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
361352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3621da177e4SLinus Torvalds {
363352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
364352f7f91STakashi Iwai 	int i;
365352f7f91STakashi Iwai 
366352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
367352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
368352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
369352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
370352f7f91STakashi Iwai 			return true;
371352f7f91STakashi Iwai 	}
372352f7f91STakashi Iwai 	return false;
3731da177e4SLinus Torvalds }
3741da177e4SLinus Torvalds 
375352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
376352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3778999bf0aSTakashi Iwai 			      int dir, int idx, int type)
378cb53c626STakashi Iwai {
379352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3808999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
381cb53c626STakashi Iwai }
382352f7f91STakashi Iwai 
3834e76a883STakashi Iwai static void print_nid_path(struct hda_codec *codec,
3844e76a883STakashi Iwai 			   const char *pfx, struct nid_path *path)
3850c8c0f56STakashi Iwai {
3860c8c0f56STakashi Iwai 	char buf[40];
387d82353e5SJoe Perches 	char *pos = buf;
3880c8c0f56STakashi Iwai 	int i;
3890c8c0f56STakashi Iwai 
390d82353e5SJoe Perches 	*pos = 0;
391d82353e5SJoe Perches 	for (i = 0; i < path->depth; i++)
392d82353e5SJoe Perches 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
393d82353e5SJoe Perches 				 pos != buf ? ":" : "",
394d82353e5SJoe Perches 				 path->path[i]);
3950c8c0f56STakashi Iwai 
396d82353e5SJoe Perches 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
3970c8c0f56STakashi Iwai }
3980c8c0f56STakashi Iwai 
399352f7f91STakashi Iwai /* called recursively */
400352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
401352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
4023ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
4033ca529d3STakashi Iwai 			     int depth)
404352f7f91STakashi Iwai {
405ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
406352f7f91STakashi Iwai 	int i, nums;
407352f7f91STakashi Iwai 
4083ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
4093ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
4103ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
4113ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
412352f7f91STakashi Iwai 
413ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
414352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
415352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
416352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
417352f7f91STakashi Iwai 			 * try to find an empty DAC
418352f7f91STakashi Iwai 			 */
419352f7f91STakashi Iwai 			if (from_nid ||
420352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
421352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
422352f7f91STakashi Iwai 				continue;
423352f7f91STakashi Iwai 		}
4243ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
4253ca529d3STakashi Iwai 		if (anchor_nid <= 0)
426352f7f91STakashi Iwai 			goto found;
427352f7f91STakashi Iwai 	}
428352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
429352f7f91STakashi Iwai 		return false;
430352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
431352f7f91STakashi Iwai 		unsigned int type;
432352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
433352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
434352f7f91STakashi Iwai 		    type == AC_WID_PIN)
435352f7f91STakashi Iwai 			continue;
436352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4373ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
438352f7f91STakashi Iwai 			goto found;
439352f7f91STakashi Iwai 	}
440352f7f91STakashi Iwai 	return false;
441352f7f91STakashi Iwai 
442352f7f91STakashi Iwai  found:
443352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
444352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
445352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
446352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
447352f7f91STakashi Iwai 	path->depth++;
448352f7f91STakashi Iwai 	return true;
449352f7f91STakashi Iwai }
450352f7f91STakashi Iwai 
451dda42bd0STakashi Iwai /**
452dda42bd0STakashi Iwai  * snd_hda_parse_nid_path - parse the widget path from the given nid to
453dda42bd0STakashi Iwai  * the target nid
454dda42bd0STakashi Iwai  * @codec: the HDA codec
455dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
456dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
457dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication
458dda42bd0STakashi Iwai  * @path: the path object to store the result
459dda42bd0STakashi Iwai  *
460dda42bd0STakashi Iwai  * Returns true if a matching path is found.
461dda42bd0STakashi Iwai  *
462dda42bd0STakashi Iwai  * The parsing behavior depends on parameters:
463352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4643ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4653ca529d3STakashi Iwai  * with the given value are evaluated.
4663ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4673ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4683ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
469352f7f91STakashi Iwai  */
470352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4713ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
472352f7f91STakashi Iwai 			    struct nid_path *path)
473352f7f91STakashi Iwai {
4743ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
475352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
476352f7f91STakashi Iwai 		path->depth++;
477352f7f91STakashi Iwai 		return true;
478352f7f91STakashi Iwai 	}
479352f7f91STakashi Iwai 	return false;
480352f7f91STakashi Iwai }
4812698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_parse_nid_path);
482352f7f91STakashi Iwai 
483dda42bd0STakashi Iwai /**
484dda42bd0STakashi Iwai  * snd_hda_add_new_path - parse the path between the given NIDs and
485dda42bd0STakashi Iwai  * add to the path list
486dda42bd0STakashi Iwai  * @codec: the HDA codec
487dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
488dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
489dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
490dda42bd0STakashi Iwai  *
491dda42bd0STakashi Iwai  * If no valid path is found, returns NULL.
492352f7f91STakashi Iwai  */
493352f7f91STakashi Iwai struct nid_path *
494352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4953ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
496352f7f91STakashi Iwai {
497352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
498352f7f91STakashi Iwai 	struct nid_path *path;
499352f7f91STakashi Iwai 
500352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
501352f7f91STakashi Iwai 		return NULL;
502352f7f91STakashi Iwai 
503f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
5043ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
505f5172a7eSTakashi Iwai 	if (path)
506f5172a7eSTakashi Iwai 		return path;
507f5172a7eSTakashi Iwai 
508352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
509352f7f91STakashi Iwai 	if (!path)
510352f7f91STakashi Iwai 		return NULL;
511352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
5123ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
513352f7f91STakashi Iwai 		return path;
514352f7f91STakashi Iwai 	/* push back */
515352f7f91STakashi Iwai 	spec->paths.used--;
516352f7f91STakashi Iwai 	return NULL;
517352f7f91STakashi Iwai }
5182698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
519352f7f91STakashi Iwai 
520980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
521980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
522980428ceSTakashi Iwai {
523980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
524980428ceSTakashi Iwai 	if (!path)
525980428ceSTakashi Iwai 		return;
526980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
527980428ceSTakashi Iwai }
528980428ceSTakashi Iwai 
5293690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
5303690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
5313690739bSTakashi Iwai {
5323690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5333690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
5343690739bSTakashi Iwai 
5353690739bSTakashi Iwai 	if (!list)
5363690739bSTakashi Iwai 		return 0;
5373690739bSTakashi Iwai 	for (; *list; list += 2)
5383690739bSTakashi Iwai 		if (*list == pin)
5393690739bSTakashi Iwai 			return list[1];
5403690739bSTakashi Iwai 	return 0;
5413690739bSTakashi Iwai }
5423690739bSTakashi Iwai 
543352f7f91STakashi Iwai /* look for an empty DAC slot */
544352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
545352f7f91STakashi Iwai 			      bool is_digital)
546352f7f91STakashi Iwai {
547352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
548352f7f91STakashi Iwai 	bool cap_digital;
549352f7f91STakashi Iwai 	int i;
550352f7f91STakashi Iwai 
551352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
552352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
553352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
554352f7f91STakashi Iwai 			continue;
555352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
556352f7f91STakashi Iwai 		if (is_digital != cap_digital)
557352f7f91STakashi Iwai 			continue;
558352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
559352f7f91STakashi Iwai 			return nid;
560352f7f91STakashi Iwai 	}
561352f7f91STakashi Iwai 	return 0;
562352f7f91STakashi Iwai }
563352f7f91STakashi Iwai 
564352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
565352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
566352f7f91STakashi Iwai {
567352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
568352f7f91STakashi Iwai 	val |= chs << 16;
569352f7f91STakashi Iwai 	return val;
570352f7f91STakashi Iwai }
571352f7f91STakashi Iwai 
57299a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
57399a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
57499a5592dSDavid Henningsson {
57599a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
57699a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
57799a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
57899a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
57999a5592dSDavid Henningsson }
58099a5592dSDavid Henningsson 
581352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
582352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
583352f7f91STakashi Iwai 				       struct nid_path *path)
584352f7f91STakashi Iwai {
585352f7f91STakashi Iwai 	int i;
586352f7f91STakashi Iwai 
587352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
588352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
589352f7f91STakashi Iwai 			return path->path[i];
590352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
591352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
592352f7f91STakashi Iwai 			return path->path[i];
593352f7f91STakashi Iwai 	}
594352f7f91STakashi Iwai 	return 0;
595352f7f91STakashi Iwai }
596352f7f91STakashi Iwai 
597352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
598352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
599352f7f91STakashi Iwai 				      struct nid_path *path)
600352f7f91STakashi Iwai {
601a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
602352f7f91STakashi Iwai 	int i;
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
605a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
606a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
607a1114a8cSTakashi Iwai 			continue;
608a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
609a1114a8cSTakashi Iwai 			return nid;
610352f7f91STakashi Iwai 	}
611352f7f91STakashi Iwai 	return 0;
612352f7f91STakashi Iwai }
613352f7f91STakashi Iwai 
614352f7f91STakashi Iwai /*
615352f7f91STakashi Iwai  * path activation / deactivation
616352f7f91STakashi Iwai  */
617352f7f91STakashi Iwai 
618352f7f91STakashi Iwai /* can have the amp-in capability? */
619352f7f91STakashi Iwai static bool has_amp_in(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_IN_AMP))
626352f7f91STakashi Iwai 		return false;
627352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
628352f7f91STakashi Iwai 		return false;
629352f7f91STakashi Iwai 	return true;
630352f7f91STakashi Iwai }
631352f7f91STakashi Iwai 
632352f7f91STakashi Iwai /* can have the amp-out capability? */
633352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
634352f7f91STakashi Iwai {
635352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
636352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
637352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
638352f7f91STakashi Iwai 
639352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
640352f7f91STakashi Iwai 		return false;
641352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
642352f7f91STakashi Iwai 		return false;
643352f7f91STakashi Iwai 	return true;
644352f7f91STakashi Iwai }
645352f7f91STakashi Iwai 
646352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
647352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6487dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
649352f7f91STakashi Iwai {
650352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
651352f7f91STakashi Iwai 	int i, n;
652352f7f91STakashi Iwai 
653352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
654352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
655352f7f91STakashi Iwai 		if (!path->active)
656352f7f91STakashi Iwai 			continue;
657352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
658352f7f91STakashi Iwai 			if (path->path[i] == nid) {
659352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
660352f7f91STakashi Iwai 					return true;
661352f7f91STakashi Iwai 				break;
662352f7f91STakashi Iwai 			}
663352f7f91STakashi Iwai 		}
664352f7f91STakashi Iwai 	}
665352f7f91STakashi Iwai 	return false;
666352f7f91STakashi Iwai }
667352f7f91STakashi Iwai 
668b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
669b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
670b1b9fbd0STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, 0)
671b1b9fbd0STakashi Iwai 
672352f7f91STakashi Iwai /* get the default amp value for the target state */
673352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6748999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
675352f7f91STakashi Iwai {
676352f7f91STakashi Iwai 	unsigned int val = 0;
677352f7f91STakashi Iwai 
678352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
679352f7f91STakashi Iwai 		/* set to 0dB */
680352f7f91STakashi Iwai 		if (enable)
681352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
682352f7f91STakashi Iwai 	}
683f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
684352f7f91STakashi Iwai 		if (!enable)
685352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
686352f7f91STakashi Iwai 	}
687352f7f91STakashi Iwai 	return val;
688352f7f91STakashi Iwai }
689352f7f91STakashi Iwai 
690352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
691352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
692352f7f91STakashi Iwai {
6938999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6948999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
695352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
696352f7f91STakashi Iwai }
697352f7f91STakashi Iwai 
6988999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6998999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
7008999bf0aSTakashi Iwai  */
7018999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
7028999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
7038999bf0aSTakashi Iwai 					   unsigned int caps)
704352f7f91STakashi Iwai {
7058999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
7068999bf0aSTakashi Iwai 
707f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
7088999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
7098999bf0aSTakashi Iwai 			mask &= ~0x80;
7108999bf0aSTakashi Iwai 	}
7118999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
7128999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
7138999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
7148999bf0aSTakashi Iwai 			mask &= ~0x7f;
7158999bf0aSTakashi Iwai 	}
7168999bf0aSTakashi Iwai 	return mask;
7178999bf0aSTakashi Iwai }
7188999bf0aSTakashi Iwai 
7198999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
7208999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
7218999bf0aSTakashi Iwai {
7228999bf0aSTakashi Iwai 	unsigned int caps;
7238999bf0aSTakashi Iwai 	unsigned int mask, val;
7248999bf0aSTakashi Iwai 
7257dddf2aeSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
726352f7f91STakashi Iwai 		return;
7278999bf0aSTakashi Iwai 
7288999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
7298999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
7308999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
7318999bf0aSTakashi Iwai 	if (!mask)
7328999bf0aSTakashi Iwai 		return;
7338999bf0aSTakashi Iwai 
7348999bf0aSTakashi Iwai 	val &= mask;
7358999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
736352f7f91STakashi Iwai }
737352f7f91STakashi Iwai 
738352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
739352f7f91STakashi Iwai 			     int i, bool enable)
740352f7f91STakashi Iwai {
741352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
742352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
7438999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
744352f7f91STakashi Iwai }
745352f7f91STakashi Iwai 
746352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
747352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
748352f7f91STakashi Iwai {
749352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
750ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
751352f7f91STakashi Iwai 	int n, nums, idx;
752352f7f91STakashi Iwai 	int type;
753352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
754352f7f91STakashi Iwai 
755ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
756352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
757352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
758352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
759352f7f91STakashi Iwai 		nums = 1;
760352f7f91STakashi Iwai 		idx = 0;
761352f7f91STakashi Iwai 	} else
762352f7f91STakashi Iwai 		idx = path->idx[i];
763352f7f91STakashi Iwai 
764352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
765352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
766352f7f91STakashi Iwai 
767352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
768352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
769352f7f91STakashi Iwai 	 */
770352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
771e4a395e7STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
772352f7f91STakashi Iwai 			continue;
7738999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
774352f7f91STakashi Iwai 	}
775352f7f91STakashi Iwai }
776352f7f91STakashi Iwai 
777dda42bd0STakashi Iwai /**
778dda42bd0STakashi Iwai  * snd_hda_activate_path - activate or deactivate the given path
779dda42bd0STakashi Iwai  * @codec: the HDA codec
780dda42bd0STakashi Iwai  * @path: the path to activate/deactivate
781dda42bd0STakashi Iwai  * @enable: flag to activate or not
782dda42bd0STakashi Iwai  * @add_aamix: enable the input from aamix NID
783dda42bd0STakashi Iwai  *
784dda42bd0STakashi Iwai  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
785352f7f91STakashi Iwai  */
786352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
787352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
788352f7f91STakashi Iwai {
78955196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
790352f7f91STakashi Iwai 	int i;
791352f7f91STakashi Iwai 
792352f7f91STakashi Iwai 	if (!enable)
793352f7f91STakashi Iwai 		path->active = false;
794352f7f91STakashi Iwai 
795352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
79655196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
79755196fffSTakashi Iwai 		if (enable && spec->power_down_unused) {
79855196fffSTakashi Iwai 			/* make sure the widget is powered up */
79955196fffSTakashi Iwai 			if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
80055196fffSTakashi Iwai 				snd_hda_codec_write(codec, nid, 0,
80155196fffSTakashi Iwai 						    AC_VERB_SET_POWER_STATE,
80255196fffSTakashi Iwai 						    AC_PWRST_D0);
80355196fffSTakashi Iwai 		}
804352f7f91STakashi Iwai 		if (enable && path->multi[i])
8058f0972dfSTakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
806352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
807352f7f91STakashi Iwai 					    path->idx[i]);
808352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
809352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
810352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
811352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
812352f7f91STakashi Iwai 	}
813352f7f91STakashi Iwai 
814352f7f91STakashi Iwai 	if (enable)
815352f7f91STakashi Iwai 		path->active = true;
816352f7f91STakashi Iwai }
8172698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
818352f7f91STakashi Iwai 
81955196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
82055196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
82155196fffSTakashi Iwai {
82255196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
823868211dbSJiri Slaby 	bool changed = false;
82455196fffSTakashi Iwai 	int i;
82555196fffSTakashi Iwai 
82655196fffSTakashi Iwai 	if (!spec->power_down_unused || path->active)
82755196fffSTakashi Iwai 		return;
82855196fffSTakashi Iwai 
82955196fffSTakashi Iwai 	for (i = 0; i < path->depth; i++) {
83055196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
831b1b9fbd0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
832b1b9fbd0STakashi Iwai 		    !is_active_nid_for_any(codec, nid)) {
83355196fffSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
83455196fffSTakashi Iwai 					    AC_VERB_SET_POWER_STATE,
83555196fffSTakashi Iwai 					    AC_PWRST_D3);
83655196fffSTakashi Iwai 			changed = true;
83755196fffSTakashi Iwai 		}
83855196fffSTakashi Iwai 	}
83955196fffSTakashi Iwai 
84055196fffSTakashi Iwai 	if (changed) {
84155196fffSTakashi Iwai 		msleep(10);
84255196fffSTakashi Iwai 		snd_hda_codec_read(codec, path->path[0], 0,
84355196fffSTakashi Iwai 				   AC_VERB_GET_POWER_STATE, 0);
84455196fffSTakashi Iwai 	}
84555196fffSTakashi Iwai }
84655196fffSTakashi Iwai 
847d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
848d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
849d5a9f1bbSTakashi Iwai {
850d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
851d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
852d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
853d5a9f1bbSTakashi Iwai 		return;
85405909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
85505909d5cSTakashi Iwai 		return;
856468ac413STakashi Iwai 	if (codec->inv_eapd)
857468ac413STakashi Iwai 		enable = !enable;
858d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
859d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
860d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
861d5a9f1bbSTakashi Iwai }
862d5a9f1bbSTakashi Iwai 
8633e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
8643e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
8653e367f15STakashi Iwai {
8663e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
8673e367f15STakashi Iwai 	if (path)
8683e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
8693e367f15STakashi Iwai }
8703e367f15STakashi Iwai 
871352f7f91STakashi Iwai 
872352f7f91STakashi Iwai /*
873352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
874352f7f91STakashi Iwai  */
875352f7f91STakashi Iwai 
8767eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
8777eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
878bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
879bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
8807eebffd3STakashi Iwai 
881352f7f91STakashi Iwai enum {
882352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
883352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
884352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
885352f7f91STakashi Iwai };
886352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
887352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
8887eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
8897eebffd3STakashi Iwai 	{
8907eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8917eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
8927eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
8937eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
8947eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
8957eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
8967eebffd3STakashi Iwai 	},
897bc2eee29STakashi Iwai 	{
898bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
899bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
900bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
901bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
902bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
903bc2eee29STakashi Iwai 	},
904352f7f91STakashi Iwai };
905352f7f91STakashi Iwai 
906352f7f91STakashi Iwai /* add dynamic controls from template */
907a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
908a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
909352f7f91STakashi Iwai 		       int cidx, unsigned long val)
910352f7f91STakashi Iwai {
911352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
912352f7f91STakashi Iwai 
91312c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
914352f7f91STakashi Iwai 	if (!knew)
915a35bd1e3STakashi Iwai 		return NULL;
916352f7f91STakashi Iwai 	knew->index = cidx;
917352f7f91STakashi Iwai 	if (get_amp_nid_(val))
918352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
919352f7f91STakashi Iwai 	knew->private_value = val;
920a35bd1e3STakashi Iwai 	return knew;
921352f7f91STakashi Iwai }
922352f7f91STakashi Iwai 
923352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
924352f7f91STakashi Iwai 				const char *pfx, const char *dir,
925352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
926352f7f91STakashi Iwai {
927975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
928352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
929a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
930a35bd1e3STakashi Iwai 		return -ENOMEM;
931a35bd1e3STakashi Iwai 	return 0;
932352f7f91STakashi Iwai }
933352f7f91STakashi Iwai 
934352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
935352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
936352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
937352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
938352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
939352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
940352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
941352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
942352f7f91STakashi Iwai 
943352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
944352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
945352f7f91STakashi Iwai {
946352f7f91STakashi Iwai 	unsigned int val;
947352f7f91STakashi Iwai 	if (!path)
948352f7f91STakashi Iwai 		return 0;
949352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
950352f7f91STakashi Iwai 	if (!val)
951352f7f91STakashi Iwai 		return 0;
952352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
953352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
954352f7f91STakashi Iwai }
955352f7f91STakashi Iwai 
956352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
957352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
958352f7f91STakashi Iwai 			       int type)
959352f7f91STakashi Iwai {
960352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
961352f7f91STakashi Iwai 	if (path) {
962352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
963352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
964352f7f91STakashi Iwai 			chs = 3; /* stereo */
965352f7f91STakashi Iwai 	}
966352f7f91STakashi Iwai 	return chs;
967352f7f91STakashi Iwai }
968352f7f91STakashi Iwai 
969352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
970352f7f91STakashi Iwai 			  struct nid_path *path)
971352f7f91STakashi Iwai {
972352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
973352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
974352f7f91STakashi Iwai }
975352f7f91STakashi Iwai 
976352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
977352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
978352f7f91STakashi Iwai  */
979352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
980352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
981352f7f91STakashi Iwai {
982352f7f91STakashi Iwai 	unsigned int val;
983352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
984352f7f91STakashi Iwai 
985352f7f91STakashi Iwai 	if (!path)
986352f7f91STakashi Iwai 		return 0;
987352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
988352f7f91STakashi Iwai 	if (!val)
989352f7f91STakashi Iwai 		return 0;
990352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
991352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
992352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
993352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
994352f7f91STakashi Iwai 		if (nums > 1) {
995352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
996352f7f91STakashi Iwai 			val |= nums << 19;
997352f7f91STakashi Iwai 		}
998352f7f91STakashi Iwai 	}
999352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1000352f7f91STakashi Iwai }
1001352f7f91STakashi Iwai 
1002352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1003352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1004352f7f91STakashi Iwai {
1005352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1006352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1007352f7f91STakashi Iwai }
1008352f7f91STakashi Iwai 
10097eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1010bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10117eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10127eebffd3STakashi Iwai {
10137eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10147eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10157eebffd3STakashi Iwai 
10167eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10177eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10187eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10197eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10207eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10217eebffd3STakashi Iwai 	}
1022bc2eee29STakashi Iwai }
10237eebffd3STakashi Iwai 
1024bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1025bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1026bc2eee29STakashi Iwai {
1027bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
10287eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
10297eebffd3STakashi Iwai }
10307eebffd3STakashi Iwai 
1031bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1032bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1033bc2eee29STakashi Iwai {
1034bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1035bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
1036bc2eee29STakashi Iwai }
1037bc2eee29STakashi Iwai 
1038247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1039247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1040247d85eeSTakashi Iwai {
1041247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1042247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1043247d85eeSTakashi Iwai }
1044247d85eeSTakashi Iwai 
1045352f7f91STakashi Iwai static const char * const channel_name[4] = {
1046352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1047352f7f91STakashi Iwai };
1048352f7f91STakashi Iwai 
1049352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1050247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1051247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1052352f7f91STakashi Iwai {
1053247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1054352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1055352f7f91STakashi Iwai 
1056352f7f91STakashi Iwai 	*index = 0;
1057352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1058247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1059352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1060352f7f91STakashi Iwai 
1061352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1062352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1063352f7f91STakashi Iwai 	 */
1064352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1065352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1066352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1067352f7f91STakashi Iwai 
1068247d85eeSTakashi Iwai 	/* multi-io channels */
1069247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1070247d85eeSTakashi Iwai 		return channel_name[ch];
1071247d85eeSTakashi Iwai 
1072352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1073352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1074247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1075247d85eeSTakashi Iwai 		 * don't name it as Speaker
1076247d85eeSTakashi Iwai 		 */
1077247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1078247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1079247d85eeSTakashi Iwai 			break;
1080352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1081352f7f91STakashi Iwai 			return "Speaker";
1082352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1083352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1084352f7f91STakashi Iwai 		break;
1085352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1086247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1087247d85eeSTakashi Iwai 		 * don't name it as Headphone
1088247d85eeSTakashi Iwai 		 */
1089247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1090247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1091247d85eeSTakashi Iwai 			break;
1092352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1093352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1094352f7f91STakashi Iwai 			break;
1095352f7f91STakashi Iwai 		*index = ch;
1096352f7f91STakashi Iwai 		return "Headphone";
109703ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
109803ad6a8cSDavid Henningsson 		/* This deals with the case where we have two DACs and
109903ad6a8cSDavid Henningsson 		 * one LO, one HP and one Speaker */
110003ad6a8cSDavid Henningsson 		if (!ch && cfg->speaker_outs && cfg->hp_outs) {
110103ad6a8cSDavid Henningsson 			bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
110203ad6a8cSDavid Henningsson 			bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
110303ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
110403ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
110503ad6a8cSDavid Henningsson 			if (hp_lo_shared)
110603ad6a8cSDavid Henningsson 				return "Headphone+LO";
110703ad6a8cSDavid Henningsson 			if (spk_lo_shared)
110803ad6a8cSDavid Henningsson 				return "Speaker+LO";
110903ad6a8cSDavid Henningsson 		}
1110247d85eeSTakashi Iwai 	}
1111247d85eeSTakashi Iwai 
1112247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1113352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
11143abb4f4dSDavid Henningsson 		return "Line Out";
1115247d85eeSTakashi Iwai 
1116352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1117352f7f91STakashi Iwai 		snd_BUG();
1118352f7f91STakashi Iwai 		return "PCM";
1119352f7f91STakashi Iwai 	}
1120352f7f91STakashi Iwai 
1121352f7f91STakashi Iwai 	return channel_name[ch];
1122352f7f91STakashi Iwai }
1123352f7f91STakashi Iwai 
1124352f7f91STakashi Iwai /*
1125352f7f91STakashi Iwai  * Parse output paths
1126352f7f91STakashi Iwai  */
1127352f7f91STakashi Iwai 
1128352f7f91STakashi Iwai /* badness definition */
1129352f7f91STakashi Iwai enum {
1130352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1131352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1132352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1133352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1134352f7f91STakashi Iwai 	/* No possible multi-ios */
11351d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1136352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1137352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1138352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1139352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1140352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1141352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
114255a63d4dSTakashi Iwai 	/* No independent HP possible */
1143bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1144352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1145352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1146352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1147352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1148352f7f91STakashi Iwai 	/* Volume widget is shared */
1149352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1150352f7f91STakashi Iwai };
1151352f7f91STakashi Iwai 
11520e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1153352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1154352f7f91STakashi Iwai  *
1155352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1156352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1157352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1158352f7f91STakashi Iwai  */
11590e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1160352f7f91STakashi Iwai {
1161d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1162352f7f91STakashi Iwai 	hda_nid_t nid;
1163352f7f91STakashi Iwai 	unsigned int val;
1164352f7f91STakashi Iwai 	int badness = 0;
1165352f7f91STakashi Iwai 
1166352f7f91STakashi Iwai 	if (!path)
1167352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
11680e614dd0STakashi Iwai 
11690e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
11700e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
11710e614dd0STakashi Iwai 		return 0; /* already evaluated */
11720e614dd0STakashi Iwai 
1173352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1174352f7f91STakashi Iwai 	if (nid) {
1175352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1176d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1177d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1178352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1179352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1180352f7f91STakashi Iwai 		else
1181352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1182352f7f91STakashi Iwai 	} else
1183352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1184352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1185352f7f91STakashi Iwai 	if (nid) {
1186352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1187352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1188352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1189352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1190352f7f91STakashi Iwai 		else
1191352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1192352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1193352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1194352f7f91STakashi Iwai 		else
1195352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1196352f7f91STakashi Iwai 	} else
1197352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1198352f7f91STakashi Iwai 	return badness;
1199352f7f91STakashi Iwai }
1200352f7f91STakashi Iwai 
120198bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1202352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1203352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1204352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1205352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1206352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1207352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1208352f7f91STakashi Iwai };
12092698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1210352f7f91STakashi Iwai 
121198bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1212352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1213352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1214352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1215352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1216352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1217352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1218352f7f91STakashi Iwai };
12192698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1220352f7f91STakashi Iwai 
12217385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
12227385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
12237385df61STakashi Iwai {
12247385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
12257385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
12267385df61STakashi Iwai 
12277385df61STakashi Iwai 	if (cfg->line_outs > idx)
12287385df61STakashi Iwai 		return spec->private_dac_nids[idx];
12297385df61STakashi Iwai 	idx -= cfg->line_outs;
12307385df61STakashi Iwai 	if (spec->multi_ios > idx)
12317385df61STakashi Iwai 		return spec->multi_io[idx].dac;
12327385df61STakashi Iwai 	return 0;
12337385df61STakashi Iwai }
12347385df61STakashi Iwai 
12357385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
12367385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
12377385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
12387385df61STakashi Iwai {
12397385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
12407385df61STakashi Iwai }
12417385df61STakashi Iwai 
1242352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1243352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1244352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1245196c1766STakashi Iwai 			   int *path_idx,
1246352f7f91STakashi Iwai 			   const struct badness_table *bad)
1247352f7f91STakashi Iwai {
1248352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1249352f7f91STakashi Iwai 	int i, j;
1250352f7f91STakashi Iwai 	int badness = 0;
1251352f7f91STakashi Iwai 	hda_nid_t dac;
1252352f7f91STakashi Iwai 
1253352f7f91STakashi Iwai 	if (!num_outs)
1254352f7f91STakashi Iwai 		return 0;
1255352f7f91STakashi Iwai 
1256352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
12570c8c0f56STakashi Iwai 		struct nid_path *path;
1258352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
12591e0b5286STakashi Iwai 
12600e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
12610e614dd0STakashi Iwai 		if (path) {
12620e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
12631e0b5286STakashi Iwai 			continue;
12641e0b5286STakashi Iwai 		}
12651e0b5286STakashi Iwai 
12663690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
12673690739bSTakashi Iwai 		if (dacs[i]) {
12683690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
12693690739bSTakashi Iwai 				badness += bad->shared_primary;
12703690739bSTakashi Iwai 		}
12713690739bSTakashi Iwai 
12723690739bSTakashi Iwai 		if (!dacs[i])
1273352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1274352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1275980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1276352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1277352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1278352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1279352f7f91STakashi Iwai 					dacs[j] = 0;
1280980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1281196c1766STakashi Iwai 					path_idx[j] = 0;
1282352f7f91STakashi Iwai 					break;
1283352f7f91STakashi Iwai 				}
1284352f7f91STakashi Iwai 			}
1285352f7f91STakashi Iwai 		}
1286352f7f91STakashi Iwai 		dac = dacs[i];
1287352f7f91STakashi Iwai 		if (!dac) {
12887385df61STakashi Iwai 			if (num_outs > 2)
12897385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
12907385df61STakashi Iwai 			if (!dac)
12917385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
12927385df61STakashi Iwai 			if (!dac)
12937385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1294352f7f91STakashi Iwai 			if (dac) {
1295352f7f91STakashi Iwai 				if (!i)
1296352f7f91STakashi Iwai 					badness += bad->shared_primary;
1297352f7f91STakashi Iwai 				else if (i == 1)
1298352f7f91STakashi Iwai 					badness += bad->shared_surr;
1299352f7f91STakashi Iwai 				else
1300352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1301352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1302352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1303352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1304352f7f91STakashi Iwai 			} else if (!i)
1305352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1306352f7f91STakashi Iwai 			else
1307352f7f91STakashi Iwai 				badness += bad->no_dac;
1308352f7f91STakashi Iwai 		}
13091fa335b0STakashi Iwai 		if (!dac)
13101fa335b0STakashi Iwai 			continue;
13113ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1312117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1313b3a8c745STakashi Iwai 			/* try with aamix */
13143ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1315b3a8c745STakashi Iwai 		}
13161fa335b0STakashi Iwai 		if (!path) {
1317352f7f91STakashi Iwai 			dac = dacs[i] = 0;
13181fa335b0STakashi Iwai 			badness += bad->no_dac;
13191fa335b0STakashi Iwai 		} else {
13204e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1321e1284af7STakashi Iwai 			path->active = true;
1322196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
13230e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1324e1284af7STakashi Iwai 		}
1325352f7f91STakashi Iwai 	}
1326352f7f91STakashi Iwai 
1327352f7f91STakashi Iwai 	return badness;
1328352f7f91STakashi Iwai }
1329352f7f91STakashi Iwai 
1330352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1331352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1332352f7f91STakashi Iwai {
1333352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1334352f7f91STakashi Iwai 	int i;
1335352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1336352f7f91STakashi Iwai 
1337352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1338352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1339352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1340352f7f91STakashi Iwai 			continue;
1341352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1342352f7f91STakashi Iwai 			if (nid_found)
1343352f7f91STakashi Iwai 				return 0;
1344352f7f91STakashi Iwai 			nid_found = nid;
1345352f7f91STakashi Iwai 		}
1346352f7f91STakashi Iwai 	}
1347352f7f91STakashi Iwai 	return nid_found;
1348352f7f91STakashi Iwai }
1349352f7f91STakashi Iwai 
1350352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1351352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1352352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1353352f7f91STakashi Iwai {
1354352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1355352f7f91STakashi Iwai 
1356352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1357352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1358352f7f91STakashi Iwai 		return false;
1359352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1360352f7f91STakashi Iwai 		return false;
1361352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1362352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1363352f7f91STakashi Iwai 		return false;
1364352f7f91STakashi Iwai 	return true;
1365352f7f91STakashi Iwai }
1366352f7f91STakashi Iwai 
1367e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1368e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1369e22aab7dSTakashi Iwai {
1370e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1371e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1372e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1373e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1374e22aab7dSTakashi Iwai 	int type, i;
1375e22aab7dSTakashi Iwai 	int num_pins = 0;
1376e22aab7dSTakashi Iwai 
1377e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1378e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1379e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1380e22aab7dSTakashi Iwai 				continue;
1381e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1382e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1383e22aab7dSTakashi Iwai 				num_pins++;
1384e22aab7dSTakashi Iwai 		}
1385e22aab7dSTakashi Iwai 	}
1386e22aab7dSTakashi Iwai 	return num_pins;
1387e22aab7dSTakashi Iwai }
1388e22aab7dSTakashi Iwai 
1389352f7f91STakashi Iwai /*
1390352f7f91STakashi Iwai  * multi-io helper
1391352f7f91STakashi Iwai  *
1392352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1393352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1394352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1395352f7f91STakashi Iwai  * the badness value.
1396352f7f91STakashi Iwai  */
1397352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1398352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1399e22aab7dSTakashi Iwai 			  bool hardwired)
1400352f7f91STakashi Iwai {
1401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1402352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1403e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1404352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1405352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1406352f7f91STakashi Iwai 	int badness = 0;
14070e614dd0STakashi Iwai 	struct nid_path *path;
1408352f7f91STakashi Iwai 
1409352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1410352f7f91STakashi Iwai 	if (old_pins >= 2)
1411352f7f91STakashi Iwai 		goto end_fill;
1412352f7f91STakashi Iwai 
1413e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1414352f7f91STakashi Iwai 	if (num_pins < 2)
1415352f7f91STakashi Iwai 		goto end_fill;
1416352f7f91STakashi Iwai 
1417352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1418352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1419352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1420352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1421352f7f91STakashi Iwai 
1422352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1423352f7f91STakashi Iwai 				continue;
1424352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1425352f7f91STakashi Iwai 				continue;
1426352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1427352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1428352f7f91STakashi Iwai 					break;
1429352f7f91STakashi Iwai 			}
1430352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1431352f7f91STakashi Iwai 				continue;
1432352f7f91STakashi Iwai 
1433352f7f91STakashi Iwai 			if (hardwired)
1434352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1435352f7f91STakashi Iwai 			else if (!dac)
1436352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1437352f7f91STakashi Iwai 			if (!dac) {
1438352f7f91STakashi Iwai 				badness++;
1439352f7f91STakashi Iwai 				continue;
1440352f7f91STakashi Iwai 			}
14413ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
14423ca529d3STakashi Iwai 						    -spec->mixer_nid);
14430c8c0f56STakashi Iwai 			if (!path) {
1444352f7f91STakashi Iwai 				badness++;
1445352f7f91STakashi Iwai 				continue;
1446352f7f91STakashi Iwai 			}
14474e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1448352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1449352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1450196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1451196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1452352f7f91STakashi Iwai 			spec->multi_ios++;
1453352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1454352f7f91STakashi Iwai 				break;
1455352f7f91STakashi Iwai 		}
1456352f7f91STakashi Iwai 	}
1457352f7f91STakashi Iwai  end_fill:
1458352f7f91STakashi Iwai 	if (badness)
1459352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1460352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1461352f7f91STakashi Iwai 		if (hardwired)
1462352f7f91STakashi Iwai 			return 1; /* nothing found */
1463352f7f91STakashi Iwai 		else
1464352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1465352f7f91STakashi Iwai 	}
1466352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1467352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1468352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1469352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1470352f7f91STakashi Iwai 		return badness;
1471352f7f91STakashi Iwai 	}
1472352f7f91STakashi Iwai 
1473352f7f91STakashi Iwai 	/* assign volume and mute controls */
14740e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
14750e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
14760e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
14770e614dd0STakashi Iwai 	}
1478352f7f91STakashi Iwai 
1479352f7f91STakashi Iwai 	return badness;
1480352f7f91STakashi Iwai }
1481352f7f91STakashi Iwai 
1482352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1483352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1484196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1485352f7f91STakashi Iwai {
1486b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1487352f7f91STakashi Iwai 	int i;
1488352f7f91STakashi Iwai 	bool found = false;
1489352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
14900c8c0f56STakashi Iwai 		struct nid_path *path;
1491352f7f91STakashi Iwai 		hda_nid_t dac;
1492352f7f91STakashi Iwai 		if (dacs[i])
1493352f7f91STakashi Iwai 			continue;
1494352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1495352f7f91STakashi Iwai 		if (!dac)
1496352f7f91STakashi Iwai 			continue;
14973ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
14983ca529d3STakashi Iwai 					    -spec->mixer_nid);
1499117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
15003ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
15010c8c0f56STakashi Iwai 		if (path) {
1502352f7f91STakashi Iwai 			dacs[i] = dac;
1503352f7f91STakashi Iwai 			found = true;
15044e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1505e1284af7STakashi Iwai 			path->active = true;
1506196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1507352f7f91STakashi Iwai 		}
1508352f7f91STakashi Iwai 	}
1509352f7f91STakashi Iwai 	return found;
1510352f7f91STakashi Iwai }
1511352f7f91STakashi Iwai 
1512c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1513c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1514c30aa7b2STakashi Iwai {
15153ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1516c30aa7b2STakashi Iwai 	struct nid_path *path;
15175ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1518c30aa7b2STakashi Iwai 
1519c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
15203ca529d3STakashi Iwai 	if (!path || !path->depth ||
15213ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1522c30aa7b2STakashi Iwai 		return 0;
15235ead56f2STakashi Iwai 	path_dac = path->path[0];
15245ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1525f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1526f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1527f87498b6STakashi Iwai 	if (!path) {
15285ead56f2STakashi Iwai 		if (dac != path_dac)
15295ead56f2STakashi Iwai 			dac = path_dac;
1530f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1531f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1532f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1533f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
15345ead56f2STakashi Iwai 		else
15355ead56f2STakashi Iwai 			dac = 0;
1536f87498b6STakashi Iwai 		if (dac)
1537f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
15383ca529d3STakashi Iwai 						    spec->mixer_nid);
1539f87498b6STakashi Iwai 	}
1540c30aa7b2STakashi Iwai 	if (!path)
1541c30aa7b2STakashi Iwai 		return 0;
15424e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1543c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1544c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1545c30aa7b2STakashi Iwai }
1546c30aa7b2STakashi Iwai 
154755a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
154855a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
154955a63d4dSTakashi Iwai {
155055a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
155155a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
155255a63d4dSTakashi Iwai 	struct nid_path *path;
155355a63d4dSTakashi Iwai 	int i, idx;
155455a63d4dSTakashi Iwai 
155555a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
155655a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
155755a63d4dSTakashi Iwai 	else
155855a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
155955a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
156055a63d4dSTakashi Iwai 	if (!path)
156155a63d4dSTakashi Iwai 		return false;
156255a63d4dSTakashi Iwai 
156355a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
156455a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
156555a63d4dSTakashi Iwai 		return true;
156655a63d4dSTakashi Iwai 
156755a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
156855a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
156955a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
157055a63d4dSTakashi Iwai 			break;
157155a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
157255a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
157355a63d4dSTakashi Iwai 			return false;
157455a63d4dSTakashi Iwai 	}
157555a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
157655a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
157755a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
157855a63d4dSTakashi Iwai 			return false;
157955a63d4dSTakashi Iwai 	}
158055a63d4dSTakashi Iwai 
158155a63d4dSTakashi Iwai 	return true;
158255a63d4dSTakashi Iwai }
158355a63d4dSTakashi Iwai 
1584a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1585a07a949bSTakashi Iwai  * shared dac pointed by the paths
1586a07a949bSTakashi Iwai  */
1587a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1588a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1589a07a949bSTakashi Iwai {
1590a07a949bSTakashi Iwai 	struct nid_path *path;
1591a07a949bSTakashi Iwai 	int i;
1592a07a949bSTakashi Iwai 
1593a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1594a07a949bSTakashi Iwai 		if (dacs[i])
1595a07a949bSTakashi Iwai 			continue;
1596a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1597a07a949bSTakashi Iwai 		if (!path)
1598a07a949bSTakashi Iwai 			continue;
1599a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1600a07a949bSTakashi Iwai 	}
1601a07a949bSTakashi Iwai }
1602a07a949bSTakashi Iwai 
1603352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1604352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1605352f7f91STakashi Iwai 			      bool fill_hardwired,
1606352f7f91STakashi Iwai 			      bool fill_mio_first)
1607352f7f91STakashi Iwai {
1608352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1609352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1610352f7f91STakashi Iwai 	int i, err, badness;
1611352f7f91STakashi Iwai 
1612352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1613352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1614352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1615352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1616352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1617352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1618352f7f91STakashi Iwai 	spec->multi_ios = 0;
1619352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1620cd5be3f9STakashi Iwai 
1621cd5be3f9STakashi Iwai 	/* clear path indices */
1622cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1623cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1624cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1625cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1626cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1627c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1628cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1629cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1630cd5be3f9STakashi Iwai 
1631352f7f91STakashi Iwai 	badness = 0;
1632352f7f91STakashi Iwai 
1633352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1634352f7f91STakashi Iwai 	if (fill_hardwired) {
1635352f7f91STakashi Iwai 		bool mapped;
1636352f7f91STakashi Iwai 		do {
1637352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1638352f7f91STakashi Iwai 					     cfg->line_out_pins,
1639196c1766STakashi Iwai 					     spec->private_dac_nids,
1640196c1766STakashi Iwai 					     spec->out_paths);
1641352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1642352f7f91STakashi Iwai 					      cfg->hp_pins,
1643196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1644196c1766STakashi Iwai 					      spec->hp_paths);
1645352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1646352f7f91STakashi Iwai 					      cfg->speaker_pins,
1647196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1648196c1766STakashi Iwai 					      spec->speaker_paths);
1649da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1650da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1651352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1652e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1653352f7f91STakashi Iwai 				if (!err)
1654352f7f91STakashi Iwai 					mapped = true;
1655352f7f91STakashi Iwai 			}
1656352f7f91STakashi Iwai 		} while (mapped);
1657352f7f91STakashi Iwai 	}
1658352f7f91STakashi Iwai 
1659352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1660196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
166198bd1115STakashi Iwai 				   spec->main_out_badness);
1662352f7f91STakashi Iwai 
1663da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1664352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1665352f7f91STakashi Iwai 		/* try to fill multi-io first */
1666e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1667352f7f91STakashi Iwai 		if (err < 0)
1668352f7f91STakashi Iwai 			return err;
1669352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1670352f7f91STakashi Iwai 	}
1671352f7f91STakashi Iwai 
1672352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1673352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1674352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1675196c1766STakashi Iwai 				      spec->hp_paths,
167698bd1115STakashi Iwai 				      spec->extra_out_badness);
1677352f7f91STakashi Iwai 		if (err < 0)
1678352f7f91STakashi Iwai 			return err;
1679352f7f91STakashi Iwai 		badness += err;
1680352f7f91STakashi Iwai 	}
1681352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1682352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1683352f7f91STakashi Iwai 				      cfg->speaker_pins,
1684352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1685196c1766STakashi Iwai 				      spec->speaker_paths,
168698bd1115STakashi Iwai 				      spec->extra_out_badness);
1687352f7f91STakashi Iwai 		if (err < 0)
1688352f7f91STakashi Iwai 			return err;
1689352f7f91STakashi Iwai 		badness += err;
1690352f7f91STakashi Iwai 	}
1691da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1692da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1693e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1694352f7f91STakashi Iwai 		if (err < 0)
1695352f7f91STakashi Iwai 			return err;
1696352f7f91STakashi Iwai 		badness += err;
1697352f7f91STakashi Iwai 	}
1698e22aab7dSTakashi Iwai 
1699c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1700c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1701c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1702c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1703c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1704c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1705c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1706c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1707c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1708c30aa7b2STakashi Iwai 	}
1709c30aa7b2STakashi Iwai 
1710da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1711da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1712e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1713e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1714352f7f91STakashi Iwai 
1715a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1716a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1717a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1718a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1719a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1720a07a949bSTakashi Iwai 		else {
1721a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1722a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1723a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1724a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1725a07a949bSTakashi Iwai 		}
1726a07a949bSTakashi Iwai 	}
1727a07a949bSTakashi Iwai 
1728a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1729c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1730a07a949bSTakashi Iwai 
1731352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1732352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1733352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1734352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1735352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1736352f7f91STakashi Iwai 		spec->multi_ios = 0;
1737352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1738352f7f91STakashi Iwai 	}
1739352f7f91STakashi Iwai 
174055a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
174155a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
174255a63d4dSTakashi Iwai 
1743a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1744a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1745a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1746a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1747a07a949bSTakashi Iwai 				   spec->hp_paths);
1748a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1749a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1750a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1751a07a949bSTakashi Iwai 				   spec->speaker_paths);
1752a07a949bSTakashi Iwai 
1753352f7f91STakashi Iwai 	return badness;
1754352f7f91STakashi Iwai }
1755352f7f91STakashi Iwai 
1756352f7f91STakashi Iwai #define DEBUG_BADNESS
1757352f7f91STakashi Iwai 
1758352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1759d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1760d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1761352f7f91STakashi Iwai #else
1762d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1763d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1764352f7f91STakashi Iwai #endif
1765352f7f91STakashi Iwai 
1766a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1767a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1768a769409cSTakashi Iwai 				      const char *pfx, int idx)
1769352f7f91STakashi Iwai {
1770a769409cSTakashi Iwai 	struct nid_path *path;
1771a769409cSTakashi Iwai 
1772a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1773a769409cSTakashi Iwai 	if (path)
17744e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1775a769409cSTakashi Iwai }
1776a769409cSTakashi Iwai 
1777a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1778a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1779a769409cSTakashi Iwai {
1780a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1781a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1782a769409cSTakashi Iwai 	int i;
1783a769409cSTakashi Iwai 
1784a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1785352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1786708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1787352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1788352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1789352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1790a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1791a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1792a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1793a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1794352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1795352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1796352f7f91STakashi Iwai 			      spec->multi_ios,
1797352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1798352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1799a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1800a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1801a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1802a769409cSTakashi Iwai 	if (cfg->hp_outs)
1803352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1804352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1805708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1806352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1807352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1808352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1809352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1810a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1811a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1812a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1813352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1814352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1815352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1816352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1817352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1818352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1819352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1820a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1821a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1822a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1823a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1824352f7f91STakashi Iwai }
1825a769409cSTakashi Iwai #else
1826a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1827a769409cSTakashi Iwai #endif
1828352f7f91STakashi Iwai 
1829352f7f91STakashi Iwai /* find all available DACs of the codec */
1830352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1831352f7f91STakashi Iwai {
1832352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1833352f7f91STakashi Iwai 	int i;
1834352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1835352f7f91STakashi Iwai 
1836352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1837352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1838352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1839352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1840352f7f91STakashi Iwai 			continue;
1841352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
18424e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1843352f7f91STakashi Iwai 			break;
1844352f7f91STakashi Iwai 		}
1845352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1846352f7f91STakashi Iwai 	}
1847352f7f91STakashi Iwai }
1848352f7f91STakashi Iwai 
1849352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1850352f7f91STakashi Iwai {
1851352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1852352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1853352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
18549314a581STakashi Iwai 	unsigned int val;
1855352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1856352f7f91STakashi Iwai 	int badness;
1857352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1858352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1859352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1860352f7f91STakashi Iwai 
1861352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1862352f7f91STakashi Iwai 	if (!best_cfg)
1863352f7f91STakashi Iwai 		return -ENOMEM;
1864352f7f91STakashi Iwai 	*best_cfg = *cfg;
1865352f7f91STakashi Iwai 
1866352f7f91STakashi Iwai 	for (;;) {
1867352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1868352f7f91STakashi Iwai 					     fill_mio_first);
1869352f7f91STakashi Iwai 		if (badness < 0) {
1870352f7f91STakashi Iwai 			kfree(best_cfg);
1871352f7f91STakashi Iwai 			return badness;
1872352f7f91STakashi Iwai 		}
1873352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1874352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1875352f7f91STakashi Iwai 			      badness);
1876a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1877352f7f91STakashi Iwai 		if (badness < best_badness) {
1878352f7f91STakashi Iwai 			best_badness = badness;
1879352f7f91STakashi Iwai 			*best_cfg = *cfg;
1880352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1881352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1882352f7f91STakashi Iwai 		}
1883352f7f91STakashi Iwai 		if (!badness)
1884352f7f91STakashi Iwai 			break;
1885352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1886352f7f91STakashi Iwai 		if (!fill_mio_first)
1887352f7f91STakashi Iwai 			continue;
1888352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1889352f7f91STakashi Iwai 		if (!fill_hardwired)
1890352f7f91STakashi Iwai 			continue;
1891352f7f91STakashi Iwai 		if (hp_spk_swapped)
1892352f7f91STakashi Iwai 			break;
1893352f7f91STakashi Iwai 		hp_spk_swapped = true;
1894352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1895352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1896352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1897352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1898352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1899352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1900352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1901352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1902352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1903352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1904352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1905352f7f91STakashi Iwai 			fill_hardwired = true;
1906352f7f91STakashi Iwai 			continue;
1907352f7f91STakashi Iwai 		}
1908352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1909352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1910352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1911352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1912352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1913352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1914352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1915352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1916352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1917352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1918352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1919352f7f91STakashi Iwai 			fill_hardwired = true;
1920352f7f91STakashi Iwai 			continue;
1921352f7f91STakashi Iwai 		}
1922352f7f91STakashi Iwai 		break;
1923352f7f91STakashi Iwai 	}
1924352f7f91STakashi Iwai 
1925352f7f91STakashi Iwai 	if (badness) {
19260c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1927352f7f91STakashi Iwai 		*cfg = *best_cfg;
1928352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1929352f7f91STakashi Iwai 	}
1930352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1931352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1932a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
1933352f7f91STakashi Iwai 
1934352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1935352f7f91STakashi Iwai 		struct nid_path *path;
1936196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1937352f7f91STakashi Iwai 		if (path)
1938352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1939d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
19407a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
19417a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1942d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
1943d89c6c0cSTakashi Iwai 				spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
1944d89c6c0cSTakashi Iwai 		}
1945352f7f91STakashi Iwai 	}
1946352f7f91STakashi Iwai 
19479314a581STakashi Iwai 	/* set initial pinctl targets */
19489314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
19499314a581STakashi Iwai 		val = PIN_HP;
19509314a581STakashi Iwai 	else
19519314a581STakashi Iwai 		val = PIN_OUT;
19529314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
19539314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
19549314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
19559314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
19569314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
19579314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
19589314a581STakashi Iwai 				cfg->speaker_pins, val);
19599314a581STakashi Iwai 	}
19609314a581STakashi Iwai 
196155a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
196255a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
196355a63d4dSTakashi Iwai 		spec->indep_hp = 0;
196455a63d4dSTakashi Iwai 
1965352f7f91STakashi Iwai 	kfree(best_cfg);
1966352f7f91STakashi Iwai 	return 0;
1967352f7f91STakashi Iwai }
1968352f7f91STakashi Iwai 
1969352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1970352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1971352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1972352f7f91STakashi Iwai {
1973352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1974352f7f91STakashi Iwai 	int i, err, noutputs;
1975352f7f91STakashi Iwai 
1976352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1977352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1978352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1979352f7f91STakashi Iwai 
1980352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1981352f7f91STakashi Iwai 		const char *name;
1982352f7f91STakashi Iwai 		int index;
1983352f7f91STakashi Iwai 		struct nid_path *path;
1984352f7f91STakashi Iwai 
1985196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1986352f7f91STakashi Iwai 		if (!path)
1987352f7f91STakashi Iwai 			continue;
1988247d85eeSTakashi Iwai 
1989247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1990352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1991352f7f91STakashi Iwai 			/* Center/LFE */
1992352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1993352f7f91STakashi Iwai 			if (err < 0)
1994352f7f91STakashi Iwai 				return err;
1995352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1996352f7f91STakashi Iwai 			if (err < 0)
1997352f7f91STakashi Iwai 				return err;
1998247d85eeSTakashi Iwai 		} else {
1999247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2000247d85eeSTakashi Iwai 			if (err < 0)
2001247d85eeSTakashi Iwai 				return err;
2002247d85eeSTakashi Iwai 		}
2003247d85eeSTakashi Iwai 
2004247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2005247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2006352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2007352f7f91STakashi Iwai 			if (err < 0)
2008352f7f91STakashi Iwai 				return err;
2009352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2010352f7f91STakashi Iwai 			if (err < 0)
2011352f7f91STakashi Iwai 				return err;
2012352f7f91STakashi Iwai 		} else {
2013352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2014352f7f91STakashi Iwai 			if (err < 0)
2015352f7f91STakashi Iwai 				return err;
2016352f7f91STakashi Iwai 		}
2017352f7f91STakashi Iwai 	}
2018352f7f91STakashi Iwai 	return 0;
2019352f7f91STakashi Iwai }
2020352f7f91STakashi Iwai 
2021c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2022196c1766STakashi Iwai 			    const char *pfx, int cidx)
2023352f7f91STakashi Iwai {
2024352f7f91STakashi Iwai 	struct nid_path *path;
2025352f7f91STakashi Iwai 	int err;
2026352f7f91STakashi Iwai 
2027196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2028352f7f91STakashi Iwai 	if (!path)
2029352f7f91STakashi Iwai 		return 0;
2030352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2031352f7f91STakashi Iwai 	if (err < 0)
2032352f7f91STakashi Iwai 		return err;
2033352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2034352f7f91STakashi Iwai 	if (err < 0)
2035352f7f91STakashi Iwai 		return err;
2036352f7f91STakashi Iwai 	return 0;
2037352f7f91STakashi Iwai }
2038352f7f91STakashi Iwai 
2039352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2040352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2041196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2042352f7f91STakashi Iwai {
2043c2c80383STakashi Iwai 	int i;
2044352f7f91STakashi Iwai 
2045352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2046c2c80383STakashi Iwai 		const char *name;
2047975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2048c2c80383STakashi Iwai 		int err, idx = 0;
2049c2c80383STakashi Iwai 
2050c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2051c2c80383STakashi Iwai 			name = "Bass Speaker";
2052c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2053c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2054352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2055c2c80383STakashi Iwai 			name = tmp;
2056352f7f91STakashi Iwai 		} else {
2057c2c80383STakashi Iwai 			name = pfx;
2058c2c80383STakashi Iwai 			idx = i;
2059352f7f91STakashi Iwai 		}
2060c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2061352f7f91STakashi Iwai 		if (err < 0)
2062352f7f91STakashi Iwai 			return err;
2063352f7f91STakashi Iwai 	}
2064352f7f91STakashi Iwai 	return 0;
2065352f7f91STakashi Iwai }
2066352f7f91STakashi Iwai 
2067352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2068352f7f91STakashi Iwai {
2069352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2070352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2071196c1766STakashi Iwai 				 spec->hp_paths,
2072352f7f91STakashi Iwai 				 "Headphone");
2073352f7f91STakashi Iwai }
2074352f7f91STakashi Iwai 
2075352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2076352f7f91STakashi Iwai {
2077352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2078352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2079196c1766STakashi Iwai 				 spec->speaker_paths,
2080352f7f91STakashi Iwai 				 "Speaker");
2081352f7f91STakashi Iwai }
2082352f7f91STakashi Iwai 
2083352f7f91STakashi Iwai /*
208438cf6f1aSTakashi Iwai  * independent HP controls
208538cf6f1aSTakashi Iwai  */
208638cf6f1aSTakashi Iwai 
20871a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
20881a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
208938cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
209038cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
209138cf6f1aSTakashi Iwai {
209238cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
209338cf6f1aSTakashi Iwai }
209438cf6f1aSTakashi Iwai 
209538cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
209638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
209738cf6f1aSTakashi Iwai {
209838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
209938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
210038cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
210138cf6f1aSTakashi Iwai 	return 0;
210238cf6f1aSTakashi Iwai }
210338cf6f1aSTakashi Iwai 
2104a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2105a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2106a1e908edSTakashi Iwai 			       int out_type);
2107a1e908edSTakashi Iwai 
210838cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
210938cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
211038cf6f1aSTakashi Iwai {
211138cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
211238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
211338cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
211438cf6f1aSTakashi Iwai 	int ret = 0;
211538cf6f1aSTakashi Iwai 
211638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
211738cf6f1aSTakashi Iwai 	if (spec->active_streams) {
211838cf6f1aSTakashi Iwai 		ret = -EBUSY;
211938cf6f1aSTakashi Iwai 		goto unlock;
212038cf6f1aSTakashi Iwai 	}
212138cf6f1aSTakashi Iwai 
212238cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2123a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2124a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2125a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2126a1e908edSTakashi Iwai 		else
2127a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2128a1e908edSTakashi Iwai 
2129a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2130a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2131a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2132a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2133a1e908edSTakashi Iwai 						   spec->out_paths[0],
2134a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2135a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2136a1e908edSTakashi Iwai 			else
2137a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2138a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2139a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2140a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2141a1e908edSTakashi Iwai 		}
2142a1e908edSTakashi Iwai 
214338cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
214438cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2145a1e908edSTakashi Iwai 			*dacp = 0;
214638cf6f1aSTakashi Iwai 		else
2147a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
214892603c59STakashi Iwai 
2149963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
215038cf6f1aSTakashi Iwai 		ret = 1;
215138cf6f1aSTakashi Iwai 	}
215238cf6f1aSTakashi Iwai  unlock:
215338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
215438cf6f1aSTakashi Iwai 	return ret;
215538cf6f1aSTakashi Iwai }
215638cf6f1aSTakashi Iwai 
215738cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
215838cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
215938cf6f1aSTakashi Iwai 	.name = "Independent HP",
216038cf6f1aSTakashi Iwai 	.info = indep_hp_info,
216138cf6f1aSTakashi Iwai 	.get = indep_hp_get,
216238cf6f1aSTakashi Iwai 	.put = indep_hp_put,
216338cf6f1aSTakashi Iwai };
216438cf6f1aSTakashi Iwai 
216538cf6f1aSTakashi Iwai 
216638cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
216738cf6f1aSTakashi Iwai {
216838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2169a1e908edSTakashi Iwai 	hda_nid_t dac;
217038cf6f1aSTakashi Iwai 
217138cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
217238cf6f1aSTakashi Iwai 		return 0;
2173a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2174a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2175a1e908edSTakashi Iwai 	else
2176a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2177a1e908edSTakashi Iwai 	if (!dac) {
217838cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
217938cf6f1aSTakashi Iwai 		return 0;
218038cf6f1aSTakashi Iwai 	}
218138cf6f1aSTakashi Iwai 
218238cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2183a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
218438cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
218538cf6f1aSTakashi Iwai 		return -ENOMEM;
218638cf6f1aSTakashi Iwai 	return 0;
218738cf6f1aSTakashi Iwai }
218838cf6f1aSTakashi Iwai 
218938cf6f1aSTakashi Iwai /*
2190352f7f91STakashi Iwai  * channel mode enum control
2191352f7f91STakashi Iwai  */
2192352f7f91STakashi Iwai 
2193352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2194352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2195352f7f91STakashi Iwai {
2196352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2197352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2198a07a949bSTakashi Iwai 	int chs;
2199352f7f91STakashi Iwai 
2200352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2201352f7f91STakashi Iwai 	uinfo->count = 1;
2202352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2203352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2204352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2205a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2206a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2207352f7f91STakashi Iwai 	return 0;
2208352f7f91STakashi Iwai }
2209352f7f91STakashi Iwai 
2210352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2211352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2212352f7f91STakashi Iwai {
2213352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2214352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2215a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2216a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2217352f7f91STakashi Iwai 	return 0;
2218352f7f91STakashi Iwai }
2219352f7f91STakashi Iwai 
2220196c1766STakashi Iwai static inline struct nid_path *
2221196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2222196c1766STakashi Iwai {
2223196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2224196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2225196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2226196c1766STakashi Iwai }
2227196c1766STakashi Iwai 
2228a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2229a5cc2509STakashi Iwai 
223065033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
223165033cc8STakashi Iwai  * used for output paths
223265033cc8STakashi Iwai  */
223365033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
223465033cc8STakashi Iwai {
223565033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
223665033cc8STakashi Iwai }
223765033cc8STakashi Iwai 
2238352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2239352f7f91STakashi Iwai {
2240352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2241352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2242352f7f91STakashi Iwai 	struct nid_path *path;
2243352f7f91STakashi Iwai 
2244196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2245352f7f91STakashi Iwai 	if (!path)
2246352f7f91STakashi Iwai 		return -EINVAL;
2247352f7f91STakashi Iwai 
2248352f7f91STakashi Iwai 	if (path->active == output)
2249352f7f91STakashi Iwai 		return 0;
2250352f7f91STakashi Iwai 
2251352f7f91STakashi Iwai 	if (output) {
22522c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
225365033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2254d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2255352f7f91STakashi Iwai 	} else {
2256d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
225765033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
22582c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
225955196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2260352f7f91STakashi Iwai 	}
2261a365fed9STakashi Iwai 
2262a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2263a5cc2509STakashi Iwai 	update_automute_all(codec);
2264a365fed9STakashi Iwai 
2265352f7f91STakashi Iwai 	return 0;
2266352f7f91STakashi Iwai }
2267352f7f91STakashi Iwai 
2268352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2269352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2270352f7f91STakashi Iwai {
2271352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2272352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2273352f7f91STakashi Iwai 	int i, ch;
2274352f7f91STakashi Iwai 
2275352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2276352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2277352f7f91STakashi Iwai 		return -EINVAL;
2278a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2279352f7f91STakashi Iwai 		return 0;
2280a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2281352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2282352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2283352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2284352f7f91STakashi Iwai 					  spec->const_channel_count);
2285352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2286352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2287352f7f91STakashi Iwai 	return 1;
2288352f7f91STakashi Iwai }
2289352f7f91STakashi Iwai 
2290352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2291352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2292352f7f91STakashi Iwai 	.name = "Channel Mode",
2293352f7f91STakashi Iwai 	.info = ch_mode_info,
2294352f7f91STakashi Iwai 	.get = ch_mode_get,
2295352f7f91STakashi Iwai 	.put = ch_mode_put,
2296352f7f91STakashi Iwai };
2297352f7f91STakashi Iwai 
2298352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2299352f7f91STakashi Iwai {
2300352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2301352f7f91STakashi Iwai 
2302352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
230312c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2304352f7f91STakashi Iwai 			return -ENOMEM;
2305352f7f91STakashi Iwai 	}
2306352f7f91STakashi Iwai 	return 0;
2307352f7f91STakashi Iwai }
2308352f7f91STakashi Iwai 
2309352f7f91STakashi Iwai /*
2310c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2311c30aa7b2STakashi Iwai  */
2312c30aa7b2STakashi Iwai 
2313c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2314c30aa7b2STakashi Iwai 
2315c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2316c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2317c30aa7b2STakashi Iwai {
2318c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2319c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2320c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2321c30aa7b2STakashi Iwai 	return 0;
2322c30aa7b2STakashi Iwai }
2323c30aa7b2STakashi Iwai 
2324c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2325a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2326a1e908edSTakashi Iwai 			       int out_type)
2327c30aa7b2STakashi Iwai {
2328a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2329c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2330c30aa7b2STakashi Iwai 
2331c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2332c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2333c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2334c30aa7b2STakashi Iwai 		return;
2335a1e908edSTakashi Iwai 
2336a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2337a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2338a1e908edSTakashi Iwai 	 */
2339a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2340a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2341a1e908edSTakashi Iwai 		do_mix = false;
2342a1e908edSTakashi Iwai 
2343c30aa7b2STakashi Iwai 	if (do_mix) {
2344c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2345c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
234655196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2347c30aa7b2STakashi Iwai 	} else {
234865033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
234965033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
235055196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2351c30aa7b2STakashi Iwai 	}
2352c30aa7b2STakashi Iwai }
2353c30aa7b2STakashi Iwai 
2354c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2355c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2356c30aa7b2STakashi Iwai {
2357c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2358c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2359c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2360c30aa7b2STakashi Iwai 
2361c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2362c30aa7b2STakashi Iwai 		return 0;
2363c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2364c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2365a1e908edSTakashi Iwai 			   spec->aamix_out_paths[0],
2366a1e908edSTakashi Iwai 			   spec->autocfg.line_out_type);
2367c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2368a1e908edSTakashi Iwai 			   spec->aamix_out_paths[1],
2369a1e908edSTakashi Iwai 			   AUTO_PIN_HP_OUT);
2370c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2371a1e908edSTakashi Iwai 			   spec->aamix_out_paths[2],
2372a1e908edSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
2373c30aa7b2STakashi Iwai 	return 1;
2374c30aa7b2STakashi Iwai }
2375c30aa7b2STakashi Iwai 
2376c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2377c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2378c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2379c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2380c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2381c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2382c30aa7b2STakashi Iwai };
2383c30aa7b2STakashi Iwai 
2384c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2385c30aa7b2STakashi Iwai {
2386c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2387c30aa7b2STakashi Iwai 
2388c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2389c30aa7b2STakashi Iwai 		return 0;
2390c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2391c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2392c30aa7b2STakashi Iwai 		return 0;
2393c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2394c30aa7b2STakashi Iwai 		return -ENOMEM;
2395a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2396c30aa7b2STakashi Iwai 	return 0;
2397c30aa7b2STakashi Iwai }
2398c30aa7b2STakashi Iwai 
2399c30aa7b2STakashi Iwai /*
2400352f7f91STakashi Iwai  * shared headphone/mic handling
2401352f7f91STakashi Iwai  */
2402352f7f91STakashi Iwai 
2403352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2404352f7f91STakashi Iwai 
2405352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2406967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2407352f7f91STakashi Iwai {
2408352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2409967303daSTakashi Iwai 	bool as_mic;
2410352f7f91STakashi Iwai 	unsigned int val;
2411967303daSTakashi Iwai 	hda_nid_t pin;
2412967303daSTakashi Iwai 
2413967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2414967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2415967303daSTakashi Iwai 
2416967303daSTakashi Iwai 	if (!force) {
2417967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2418967303daSTakashi Iwai 		if (as_mic) {
2419967303daSTakashi Iwai 			if (val & PIN_IN)
2420967303daSTakashi Iwai 				return;
2421967303daSTakashi Iwai 		} else {
2422967303daSTakashi Iwai 			if (val & PIN_OUT)
2423967303daSTakashi Iwai 				return;
2424967303daSTakashi Iwai 		}
2425967303daSTakashi Iwai 	}
2426352f7f91STakashi Iwai 
2427352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2428967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2429967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2430967303daSTakashi Iwai 	 */
2431352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2432352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2433352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2434352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
24357594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2436967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2437352f7f91STakashi Iwai 	}
2438352f7f91STakashi Iwai 
24398ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2440967303daSTakashi Iwai 		if (as_mic)
2441967303daSTakashi Iwai 			val |= PIN_IN;
2442967303daSTakashi Iwai 		else
2443967303daSTakashi Iwai 			val = PIN_HP;
24442c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2445963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
24468ba955ceSTakashi Iwai 	}
2447352f7f91STakashi Iwai }
2448352f7f91STakashi Iwai 
2449352f7f91STakashi Iwai /* create a shared input with the headphone out */
2450967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2451352f7f91STakashi Iwai {
2452352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2453352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2454352f7f91STakashi Iwai 	unsigned int defcfg;
2455352f7f91STakashi Iwai 	hda_nid_t nid;
2456352f7f91STakashi Iwai 
2457967303daSTakashi Iwai 	if (!spec->hp_mic) {
2458967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2459352f7f91STakashi Iwai 			return 0;
2460967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2461967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2462967303daSTakashi Iwai 		 */
2463967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2464967303daSTakashi Iwai 			return 0;
2465967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2466352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2467352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2468352f7f91STakashi Iwai 				return 0;
2469967303daSTakashi Iwai 		}
2470967303daSTakashi Iwai 	}
2471352f7f91STakashi Iwai 
2472967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2473967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2474967303daSTakashi Iwai 		return 0;
2475967303daSTakashi Iwai 
2476967303daSTakashi Iwai 	nid = 0;
2477967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2478967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2479967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2480967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2481967303daSTakashi Iwai 	if (!nid)
2482967303daSTakashi Iwai 		return 0;
2483352f7f91STakashi Iwai 
2484352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2485352f7f91STakashi Iwai 		return 0; /* no input */
2486352f7f91STakashi Iwai 
2487967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2488967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2489cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2490967303daSTakashi Iwai 	cfg->num_inputs++;
2491967303daSTakashi Iwai 	spec->hp_mic = 1;
2492967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2493967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2494967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
24954e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2496352f7f91STakashi Iwai 	return 0;
2497352f7f91STakashi Iwai }
2498352f7f91STakashi Iwai 
2499978e77e7STakashi Iwai /*
2500978e77e7STakashi Iwai  * output jack mode
2501978e77e7STakashi Iwai  */
25025f171baaSTakashi Iwai 
25035f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
25045f171baaSTakashi Iwai 
25055f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
25065f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
25075f171baaSTakashi Iwai };
25085f171baaSTakashi Iwai 
2509978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2510978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2511978e77e7STakashi Iwai {
25125f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2513978e77e7STakashi Iwai }
2514978e77e7STakashi Iwai 
2515978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2516978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2517978e77e7STakashi Iwai {
2518978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2519978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2520978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2521978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2522978e77e7STakashi Iwai 	else
2523978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2524978e77e7STakashi Iwai 	return 0;
2525978e77e7STakashi Iwai }
2526978e77e7STakashi Iwai 
2527978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2528978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2529978e77e7STakashi Iwai {
2530978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2531978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2532978e77e7STakashi Iwai 	unsigned int val;
2533978e77e7STakashi Iwai 
2534978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2535978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2536978e77e7STakashi Iwai 		return 0;
2537978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2538978e77e7STakashi Iwai 	return 1;
2539978e77e7STakashi Iwai }
2540978e77e7STakashi Iwai 
2541978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2542978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2543978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2544978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2545978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2546978e77e7STakashi Iwai };
2547978e77e7STakashi Iwai 
2548978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2549978e77e7STakashi Iwai {
2550978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2551978e77e7STakashi Iwai 	int i;
2552978e77e7STakashi Iwai 
2553978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2554978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2555978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2556978e77e7STakashi Iwai 			return true;
2557978e77e7STakashi Iwai 	}
2558978e77e7STakashi Iwai 	return false;
2559978e77e7STakashi Iwai }
2560978e77e7STakashi Iwai 
2561978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2562978e77e7STakashi Iwai 			       char *name, size_t name_len)
2563978e77e7STakashi Iwai {
2564978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2565978e77e7STakashi Iwai 	int idx = 0;
2566978e77e7STakashi Iwai 
2567978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2568978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2569978e77e7STakashi Iwai 
2570978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2571978e77e7STakashi Iwai 		;
2572978e77e7STakashi Iwai }
2573978e77e7STakashi Iwai 
25745f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
25755f171baaSTakashi Iwai {
25765f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2577f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
25785f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
25795f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
25805f171baaSTakashi Iwai 			return 2;
25815f171baaSTakashi Iwai 	}
25825f171baaSTakashi Iwai 	return 1;
25835f171baaSTakashi Iwai }
25845f171baaSTakashi Iwai 
2585978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2586978e77e7STakashi Iwai 				 hda_nid_t *pins)
2587978e77e7STakashi Iwai {
2588978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2589978e77e7STakashi Iwai 	int i;
2590978e77e7STakashi Iwai 
2591978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2592978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2593ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
25945f171baaSTakashi Iwai 			continue;
25955f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2596978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2597975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2598978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2599978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2600978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2601978e77e7STakashi Iwai 			if (!knew)
2602978e77e7STakashi Iwai 				return -ENOMEM;
2603978e77e7STakashi Iwai 			knew->private_value = pin;
2604978e77e7STakashi Iwai 		}
2605978e77e7STakashi Iwai 	}
2606978e77e7STakashi Iwai 
2607978e77e7STakashi Iwai 	return 0;
2608978e77e7STakashi Iwai }
2609978e77e7STakashi Iwai 
261029476558STakashi Iwai /*
261129476558STakashi Iwai  * input jack mode
261229476558STakashi Iwai  */
261329476558STakashi Iwai 
261429476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
261529476558STakashi Iwai #define NUM_VREFS	6
261629476558STakashi Iwai 
261729476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
261829476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
261929476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
262029476558STakashi Iwai };
262129476558STakashi Iwai 
262229476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
262329476558STakashi Iwai {
262429476558STakashi Iwai 	unsigned int pincap;
262529476558STakashi Iwai 
262629476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
262729476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
262829476558STakashi Iwai 	/* filter out unusual vrefs */
262929476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
263029476558STakashi Iwai 	return pincap;
263129476558STakashi Iwai }
263229476558STakashi Iwai 
263329476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
263429476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
263529476558STakashi Iwai {
263629476558STakashi Iwai 	unsigned int i, n = 0;
263729476558STakashi Iwai 
263829476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
263929476558STakashi Iwai 		if (vref_caps & (1 << i)) {
264029476558STakashi Iwai 			if (n == item_idx)
264129476558STakashi Iwai 				return i;
264229476558STakashi Iwai 			n++;
264329476558STakashi Iwai 		}
264429476558STakashi Iwai 	}
264529476558STakashi Iwai 	return 0;
264629476558STakashi Iwai }
264729476558STakashi Iwai 
264829476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
264929476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
265029476558STakashi Iwai {
265129476558STakashi Iwai 	unsigned int i, n = 0;
265229476558STakashi Iwai 
265329476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
265429476558STakashi Iwai 		if (i == idx)
265529476558STakashi Iwai 			return n;
265629476558STakashi Iwai 		if (vref_caps & (1 << i))
265729476558STakashi Iwai 			n++;
265829476558STakashi Iwai 	}
265929476558STakashi Iwai 	return 0;
266029476558STakashi Iwai }
266129476558STakashi Iwai 
266229476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
266329476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
266429476558STakashi Iwai {
266529476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
266629476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
266729476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
266829476558STakashi Iwai 
266929476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
267029476558STakashi Iwai 				 vref_texts);
267129476558STakashi Iwai 	/* set the right text */
267229476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
267329476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
267429476558STakashi Iwai 	return 0;
267529476558STakashi Iwai }
267629476558STakashi Iwai 
267729476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
267829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
267929476558STakashi Iwai {
268029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
268129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
268229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
268329476558STakashi Iwai 	unsigned int idx;
268429476558STakashi Iwai 
268529476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
268629476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
268729476558STakashi Iwai 	return 0;
268829476558STakashi Iwai }
268929476558STakashi Iwai 
269029476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
269129476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
269229476558STakashi Iwai {
269329476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
269429476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
269529476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
269629476558STakashi Iwai 	unsigned int val, idx;
269729476558STakashi Iwai 
269829476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
269929476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
270029476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
270129476558STakashi Iwai 		return 0;
270229476558STakashi Iwai 
270329476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
270429476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
270529476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
270629476558STakashi Iwai 	return 1;
270729476558STakashi Iwai }
270829476558STakashi Iwai 
270929476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
271029476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
271129476558STakashi Iwai 	.info = in_jack_mode_info,
271229476558STakashi Iwai 	.get = in_jack_mode_get,
271329476558STakashi Iwai 	.put = in_jack_mode_put,
271429476558STakashi Iwai };
271529476558STakashi Iwai 
27165f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
27175f171baaSTakashi Iwai {
27185f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
27195f171baaSTakashi Iwai 	int nitems = 0;
2720f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
27215f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
27225f171baaSTakashi Iwai 	return nitems ? nitems : 1;
27235f171baaSTakashi Iwai }
27245f171baaSTakashi Iwai 
272529476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
272629476558STakashi Iwai {
272729476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
272829476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2729975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
27305f171baaSTakashi Iwai 	unsigned int defcfg;
27315f171baaSTakashi Iwai 
2732f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2733f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
273429476558STakashi Iwai 
273529476558STakashi Iwai 	/* no jack mode for fixed pins */
273629476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
273729476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
273829476558STakashi Iwai 		return 0;
273929476558STakashi Iwai 
274029476558STakashi Iwai 	/* no multiple vref caps? */
27415f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
274229476558STakashi Iwai 		return 0;
274329476558STakashi Iwai 
274429476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
274529476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
274629476558STakashi Iwai 	if (!knew)
274729476558STakashi Iwai 		return -ENOMEM;
274829476558STakashi Iwai 	knew->private_value = pin;
274929476558STakashi Iwai 	return 0;
275029476558STakashi Iwai }
275129476558STakashi Iwai 
27525f171baaSTakashi Iwai /*
27535f171baaSTakashi Iwai  * HP/mic shared jack mode
27545f171baaSTakashi Iwai  */
27555f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
27565f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
27575f171baaSTakashi Iwai {
27585f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27595f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27605f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27615f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27625f171baaSTakashi Iwai 	const char *text = NULL;
27635f171baaSTakashi Iwai 	int idx;
27645f171baaSTakashi Iwai 
27655f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
27665f171baaSTakashi Iwai 	uinfo->count = 1;
27675f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
27685f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
27695f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
27705f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
27715f171baaSTakashi Iwai 	if (idx < out_jacks) {
27725f171baaSTakashi Iwai 		if (out_jacks > 1)
27735f171baaSTakashi Iwai 			text = out_jack_texts[idx];
27745f171baaSTakashi Iwai 		else
27755f171baaSTakashi Iwai 			text = "Headphone Out";
27765f171baaSTakashi Iwai 	} else {
27775f171baaSTakashi Iwai 		idx -= out_jacks;
27785f171baaSTakashi Iwai 		if (in_jacks > 1) {
27795f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27805f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
27815f171baaSTakashi Iwai 		} else
27825f171baaSTakashi Iwai 			text = "Mic In";
27835f171baaSTakashi Iwai 	}
27845f171baaSTakashi Iwai 
27855f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
27865f171baaSTakashi Iwai 	return 0;
27875f171baaSTakashi Iwai }
27885f171baaSTakashi Iwai 
27895f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
27905f171baaSTakashi Iwai {
27915f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27925f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27935f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
27945f171baaSTakashi Iwai 	int idx = 0;
27955f171baaSTakashi Iwai 
27965f171baaSTakashi Iwai 	if (val & PIN_OUT) {
27975f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
27985f171baaSTakashi Iwai 			idx = 1;
27995f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
28005f171baaSTakashi Iwai 		idx = out_jacks;
28015f171baaSTakashi Iwai 		if (in_jacks > 1) {
28025f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
28035f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
28045f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
28055f171baaSTakashi Iwai 		}
28065f171baaSTakashi Iwai 	}
28075f171baaSTakashi Iwai 	return idx;
28085f171baaSTakashi Iwai }
28095f171baaSTakashi Iwai 
28105f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
28115f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
28125f171baaSTakashi Iwai {
28135f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28145f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
28155f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
28165f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
28175f171baaSTakashi Iwai 	return 0;
28185f171baaSTakashi Iwai }
28195f171baaSTakashi Iwai 
28205f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
28215f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
28225f171baaSTakashi Iwai {
28235f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28245f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
28255f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
28265f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
28275f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
28285f171baaSTakashi Iwai 
28295f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
28305f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
28315f171baaSTakashi Iwai 	if (oldval == idx)
28325f171baaSTakashi Iwai 		return 0;
28335f171baaSTakashi Iwai 
28345f171baaSTakashi Iwai 	if (idx < out_jacks) {
28355f171baaSTakashi Iwai 		if (out_jacks > 1)
28365f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
28375f171baaSTakashi Iwai 		else
28385f171baaSTakashi Iwai 			val = PIN_HP;
28395f171baaSTakashi Iwai 	} else {
28405f171baaSTakashi Iwai 		idx -= out_jacks;
28415f171baaSTakashi Iwai 		if (in_jacks > 1) {
28425f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
28435f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
28443f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
28453f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
28465f171baaSTakashi Iwai 		} else
284716c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
28485f171baaSTakashi Iwai 	}
28495f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2850963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
28518ba955ceSTakashi Iwai 
28525f171baaSTakashi Iwai 	return 1;
28535f171baaSTakashi Iwai }
28545f171baaSTakashi Iwai 
28555f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
28565f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
28575f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
28585f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
28595f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
28605f171baaSTakashi Iwai };
28615f171baaSTakashi Iwai 
28625f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
28635f171baaSTakashi Iwai {
28645f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28655f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
28665f171baaSTakashi Iwai 
28675f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
28685f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
28695f171baaSTakashi Iwai 	if (!knew)
28705f171baaSTakashi Iwai 		return -ENOMEM;
28715f171baaSTakashi Iwai 	knew->private_value = pin;
28728ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
28735f171baaSTakashi Iwai 	return 0;
28745f171baaSTakashi Iwai }
2875352f7f91STakashi Iwai 
2876352f7f91STakashi Iwai /*
2877352f7f91STakashi Iwai  * Parse input paths
2878352f7f91STakashi Iwai  */
2879352f7f91STakashi Iwai 
2880352f7f91STakashi Iwai /* add the powersave loopback-list entry */
28810186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2882352f7f91STakashi Iwai {
2883352f7f91STakashi Iwai 	struct hda_amp_list *list;
2884352f7f91STakashi Iwai 
28850186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
28860186f4f4STakashi Iwai 	if (!list)
28870186f4f4STakashi Iwai 		return -ENOMEM;
2888352f7f91STakashi Iwai 	list->nid = mix;
2889352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2890352f7f91STakashi Iwai 	list->idx = idx;
28910186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
28920186f4f4STakashi Iwai 	return 0;
2893cb53c626STakashi Iwai }
2894cb53c626STakashi Iwai 
28952ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
28962ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
28972ded3e5bSTakashi Iwai  */
28982ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
28992ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
29002ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
29012ded3e5bSTakashi Iwai {
29022ded3e5bSTakashi Iwai 	int idx, num_conns;
29032ded3e5bSTakashi Iwai 	const hda_nid_t *list;
29042ded3e5bSTakashi Iwai 	hda_nid_t nid;
29052ded3e5bSTakashi Iwai 
29062ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
29072ded3e5bSTakashi Iwai 	if (idx < 0)
29082ded3e5bSTakashi Iwai 		return false;
29092ded3e5bSTakashi Iwai 
29102ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
29112ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
29122ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
29132ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
29142ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
29152ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
29162ded3e5bSTakashi Iwai 		return true;
29172ded3e5bSTakashi Iwai 
29182ded3e5bSTakashi Iwai 	/* check leaf node */
29192ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
29202ded3e5bSTakashi Iwai 	if (num_conns < idx)
29212ded3e5bSTakashi Iwai 		return false;
29222ded3e5bSTakashi Iwai 	nid = list[idx];
292343a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
292443a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
29252ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
292643a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
292743a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
29282ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
29292ded3e5bSTakashi Iwai 
29302ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
29312ded3e5bSTakashi Iwai }
29322ded3e5bSTakashi Iwai 
2933352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2934196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2935196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2936352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
29371da177e4SLinus Torvalds {
2938352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2939352f7f91STakashi Iwai 	struct nid_path *path;
29402ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
2941352f7f91STakashi Iwai 	int err, idx;
29421da177e4SLinus Torvalds 
29432ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
29442ded3e5bSTakashi Iwai 		return 0;
2945352f7f91STakashi Iwai 
29463ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2947352f7f91STakashi Iwai 	if (!path)
2948352f7f91STakashi Iwai 		return -EINVAL;
29494e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
2950196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2951352f7f91STakashi Iwai 
2952352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
29532ded3e5bSTakashi Iwai 	if (mix_val) {
29542ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
2955d13bd412STakashi Iwai 		if (err < 0)
29561da177e4SLinus Torvalds 			return err;
29572ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
29581da177e4SLinus Torvalds 	}
29591da177e4SLinus Torvalds 
29602ded3e5bSTakashi Iwai 	if (mute_val) {
29612ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
2962d13bd412STakashi Iwai 		if (err < 0)
29631da177e4SLinus Torvalds 			return err;
29642ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
29651da177e4SLinus Torvalds 	}
29661da177e4SLinus Torvalds 
2967352f7f91STakashi Iwai 	path->active = true;
29680186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
29690186f4f4STakashi Iwai 	if (err < 0)
29700186f4f4STakashi Iwai 		return err;
2971e4a395e7STakashi Iwai 
2972e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
2973e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
2974e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
2975e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
2976e4a395e7STakashi Iwai 		if (path) {
29774e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
2978e4a395e7STakashi Iwai 			path->active = true;
2979e4a395e7STakashi Iwai 			spec->loopback_merge_path =
2980e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
2981e4a395e7STakashi Iwai 		}
2982e4a395e7STakashi Iwai 	}
2983e4a395e7STakashi Iwai 
2984352f7f91STakashi Iwai 	return 0;
29851da177e4SLinus Torvalds }
29861da177e4SLinus Torvalds 
2987352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
29881da177e4SLinus Torvalds {
2989352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2990352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2991352f7f91STakashi Iwai }
2992352f7f91STakashi Iwai 
2993352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2994352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2995352f7f91STakashi Iwai {
2996352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2997352f7f91STakashi Iwai 	hda_nid_t nid;
2998352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2999352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
3000352f7f91STakashi Iwai 	int i, nums = 0;
3001352f7f91STakashi Iwai 
3002352f7f91STakashi Iwai 	nid = codec->start_nid;
3003352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
3004352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3005352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3006352f7f91STakashi Iwai 
3007352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3008352f7f91STakashi Iwai 			continue;
3009352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3010352f7f91STakashi Iwai 		if (++nums >= max_nums)
3011352f7f91STakashi Iwai 			break;
3012352f7f91STakashi Iwai 	}
3013352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
30140ffd534eSTakashi Iwai 
30150ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
30160ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
30170ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
30180ffd534eSTakashi Iwai 
3019352f7f91STakashi Iwai 	return nums;
3020352f7f91STakashi Iwai }
3021352f7f91STakashi Iwai 
3022352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3023352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3024352f7f91STakashi Iwai  */
3025352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3026352f7f91STakashi Iwai {
3027352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3028352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
30293a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3030352f7f91STakashi Iwai 	int i, n, nums;
3031352f7f91STakashi Iwai 
3032352f7f91STakashi Iwai 	nums = 0;
30333a65bcdcSTakashi Iwai 	ok_bits = 0;
3034352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3035352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
30363a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3037352f7f91STakashi Iwai 				break;
3038352f7f91STakashi Iwai 		}
30393a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
30403a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
30413a65bcdcSTakashi Iwai 			nums++;
30423a65bcdcSTakashi Iwai 		}
3043352f7f91STakashi Iwai 	}
3044352f7f91STakashi Iwai 
30453a65bcdcSTakashi Iwai 	if (!ok_bits) {
3046352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3047352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3048352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
30493a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3050352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3051352f7f91STakashi Iwai 					break;
3052352f7f91STakashi Iwai 				}
3053352f7f91STakashi Iwai 			}
3054352f7f91STakashi Iwai 		}
3055352f7f91STakashi Iwai 
30564e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3057352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3058352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
30593a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
30603a65bcdcSTakashi Iwai 		nums = 0;
30613a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
30623a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
30633a65bcdcSTakashi Iwai 				continue;
30643a65bcdcSTakashi Iwai 			if (n != nums) {
30653a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3066980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3067980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3068980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
30693a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
30703a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
30713a65bcdcSTakashi Iwai 				}
3072980428ceSTakashi Iwai 			}
30733a65bcdcSTakashi Iwai 			nums++;
30743a65bcdcSTakashi Iwai 		}
3075352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3076352f7f91STakashi Iwai 	}
3077352f7f91STakashi Iwai 
3078967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3079967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
30804e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3081352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3082352f7f91STakashi Iwai 	}
3083352f7f91STakashi Iwai 
3084352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3085352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3086352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3087352f7f91STakashi Iwai 
30881da177e4SLinus Torvalds 	return 0;
30891da177e4SLinus Torvalds }
30901da177e4SLinus Torvalds 
3091f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3092f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
30939dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
30949dba205bSTakashi Iwai 				const char *label, int anchor)
3095f3fc0b0bSTakashi Iwai {
3096f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3097f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3098f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3099f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3100f3fc0b0bSTakashi Iwai 	int c;
3101f3fc0b0bSTakashi Iwai 
3102f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3103f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3104f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3105f3fc0b0bSTakashi Iwai 
3106f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3107f3fc0b0bSTakashi Iwai 			continue;
3108f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3109f3fc0b0bSTakashi Iwai 		if (!path)
3110f3fc0b0bSTakashi Iwai 			continue;
31114e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3112f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3113f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3114f3fc0b0bSTakashi Iwai 
3115f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3116967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3117967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3118f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
31196194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3120f3fc0b0bSTakashi Iwai 			imux_added = true;
3121f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3122f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3123f3fc0b0bSTakashi Iwai 		}
3124f3fc0b0bSTakashi Iwai 	}
3125f3fc0b0bSTakashi Iwai 
3126f3fc0b0bSTakashi Iwai 	return 0;
3127f3fc0b0bSTakashi Iwai }
3128f3fc0b0bSTakashi Iwai 
31291da177e4SLinus Torvalds /*
3130352f7f91STakashi Iwai  * create playback/capture controls for input pins
31311da177e4SLinus Torvalds  */
31329dba205bSTakashi Iwai 
3133c970042cSTakashi Iwai /* fill the label for each input at first */
3134c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3135c970042cSTakashi Iwai {
3136c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3137c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3138c970042cSTakashi Iwai 	int i;
3139c970042cSTakashi Iwai 
3140c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3141c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3142c970042cSTakashi Iwai 		const char *label;
3143c970042cSTakashi Iwai 		int j, idx;
3144c970042cSTakashi Iwai 
3145c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3146c970042cSTakashi Iwai 			continue;
3147c970042cSTakashi Iwai 
3148c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3149c970042cSTakashi Iwai 		idx = 0;
31508e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3151c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3152c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3153c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3154c970042cSTakashi Iwai 				break;
3155c970042cSTakashi Iwai 			}
3156c970042cSTakashi Iwai 		}
3157c970042cSTakashi Iwai 
3158c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3159c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3160c970042cSTakashi Iwai 	}
3161c970042cSTakashi Iwai 
3162c970042cSTakashi Iwai 	return 0;
3163c970042cSTakashi Iwai }
3164c970042cSTakashi Iwai 
31659dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
31669dba205bSTakashi Iwai 
3167352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3168a7da6ce5STakashi Iwai {
3169352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3170352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3171352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3172352f7f91STakashi Iwai 	int num_adcs;
3173c970042cSTakashi Iwai 	int i, err;
31742c12c30dSTakashi Iwai 	unsigned int val;
3175a7da6ce5STakashi Iwai 
3176352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3177352f7f91STakashi Iwai 	if (num_adcs < 0)
3178352f7f91STakashi Iwai 		return 0;
3179352f7f91STakashi Iwai 
3180c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3181c970042cSTakashi Iwai 	if (err < 0)
3182c970042cSTakashi Iwai 		return err;
3183c970042cSTakashi Iwai 
3184352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3185352f7f91STakashi Iwai 		hda_nid_t pin;
3186352f7f91STakashi Iwai 
3187352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3188352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3189352f7f91STakashi Iwai 			continue;
3190352f7f91STakashi Iwai 
31912c12c30dSTakashi Iwai 		val = PIN_IN;
31922c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
31932c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
319493c9d8aeSTakashi Iwai 		if (pin != spec->hp_mic_pin)
31952c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
31962c12c30dSTakashi Iwai 
3197352f7f91STakashi Iwai 		if (mixer) {
3198352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3199196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3200c970042cSTakashi Iwai 						       spec->input_labels[i],
3201c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3202c970042cSTakashi Iwai 						       mixer);
3203a7da6ce5STakashi Iwai 				if (err < 0)
3204a7da6ce5STakashi Iwai 					return err;
3205a7da6ce5STakashi Iwai 			}
3206352f7f91STakashi Iwai 		}
3207352f7f91STakashi Iwai 
3208c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3209c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3210f3fc0b0bSTakashi Iwai 		if (err < 0)
3211f3fc0b0bSTakashi Iwai 			return err;
321229476558STakashi Iwai 
3213f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
321429476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
321529476558STakashi Iwai 			if (err < 0)
321629476558STakashi Iwai 				return err;
321729476558STakashi Iwai 		}
3218352f7f91STakashi Iwai 	}
3219f3fc0b0bSTakashi Iwai 
3220f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
322174f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
32229dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3223f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3224f3fc0b0bSTakashi Iwai 		if (err < 0)
3225f3fc0b0bSTakashi Iwai 			return err;
322682d04e10STakashi Iwai 		else
322782d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3228352f7f91STakashi Iwai 	}
3229352f7f91STakashi Iwai 
3230a7da6ce5STakashi Iwai 	return 0;
3231a7da6ce5STakashi Iwai }
3232a7da6ce5STakashi Iwai 
32331da177e4SLinus Torvalds 
3234352f7f91STakashi Iwai /*
3235352f7f91STakashi Iwai  * input source mux
3236352f7f91STakashi Iwai  */
3237352f7f91STakashi Iwai 
3238c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3239c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3240352f7f91STakashi Iwai {
3241352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3242b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3243b56fa1edSDavid Henningsson 		snd_BUG();
3244b56fa1edSDavid Henningsson 		return NULL;
3245b56fa1edSDavid Henningsson 	}
3246352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3247352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3248d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3249b56fa1edSDavid Henningsson 		snd_BUG();
3250b56fa1edSDavid Henningsson 		return NULL;
3251b56fa1edSDavid Henningsson 	}
3252c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
325397ec558aSTakashi Iwai }
3254352f7f91STakashi Iwai 
3255352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3256352f7f91STakashi Iwai 		      unsigned int idx);
3257352f7f91STakashi Iwai 
3258352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3259352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3260352f7f91STakashi Iwai {
3261352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3262352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3263352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3264352f7f91STakashi Iwai }
3265352f7f91STakashi Iwai 
3266352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3267352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3268352f7f91STakashi Iwai {
3269352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3270352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
32712a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
32722a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3273352f7f91STakashi Iwai 
3274352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
32751da177e4SLinus Torvalds 	return 0;
32761da177e4SLinus Torvalds }
32771da177e4SLinus Torvalds 
3278352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3279352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
32801da177e4SLinus Torvalds {
3281352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
32822a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3283352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3284352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3285352f7f91STakashi Iwai }
3286352f7f91STakashi Iwai 
3287352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
32881da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3289352f7f91STakashi Iwai 	.name = "Input Source",
3290352f7f91STakashi Iwai 	.info = mux_enum_info,
3291352f7f91STakashi Iwai 	.get = mux_enum_get,
3292352f7f91STakashi Iwai 	.put = mux_enum_put,
32931da177e4SLinus Torvalds };
3294071c73adSTakashi Iwai 
329547d46abbSTakashi Iwai /*
329647d46abbSTakashi Iwai  * capture volume and capture switch ctls
329747d46abbSTakashi Iwai  */
329847d46abbSTakashi Iwai 
3299352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3300352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3301071c73adSTakashi Iwai 
330247d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3303352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3304352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3305352f7f91STakashi Iwai 			  put_call_t func, int type)
3306352f7f91STakashi Iwai {
3307352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3308352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3309352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3310352f7f91STakashi Iwai 	struct nid_path *path;
3311352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3312071c73adSTakashi Iwai 
3313352f7f91STakashi Iwai 	imux = &spec->input_mux;
3314a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3315352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
331647d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
331747d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
331847d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
331947d46abbSTakashi Iwai 	 */
3320352f7f91STakashi Iwai 	codec->cached_write = 1;
3321352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3322c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3323c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3324352f7f91STakashi Iwai 			continue;
3325352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3326352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3327352f7f91STakashi Iwai 		if (err < 0)
3328352f7f91STakashi Iwai 			goto error;
3329352f7f91STakashi Iwai 	}
3330352f7f91STakashi Iwai  error:
3331352f7f91STakashi Iwai 	codec->cached_write = 0;
3332352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3333dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec); /* flush the updates */
3334352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
33357fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3336352f7f91STakashi Iwai 	return err;
3337352f7f91STakashi Iwai }
3338352f7f91STakashi Iwai 
3339352f7f91STakashi Iwai /* capture volume ctl callbacks */
3340352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3341352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3342352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3343352f7f91STakashi Iwai 
3344352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3345352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3346352f7f91STakashi Iwai {
3347352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3348352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3349352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3350352f7f91STakashi Iwai }
3351352f7f91STakashi Iwai 
3352352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3353352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3354352f7f91STakashi Iwai 	.name = "Capture Volume",
3355352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3356352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3357352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3358352f7f91STakashi Iwai 	.info = cap_vol_info,
3359352f7f91STakashi Iwai 	.get = cap_vol_get,
3360352f7f91STakashi Iwai 	.put = cap_vol_put,
3361352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3362352f7f91STakashi Iwai };
3363352f7f91STakashi Iwai 
3364352f7f91STakashi Iwai /* capture switch ctl callbacks */
3365352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3366352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3367352f7f91STakashi Iwai 
3368352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3369352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3370352f7f91STakashi Iwai {
3371a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3372352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3373352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3374352f7f91STakashi Iwai }
3375352f7f91STakashi Iwai 
3376352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3377352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3378352f7f91STakashi Iwai 	.name = "Capture Switch",
3379352f7f91STakashi Iwai 	.info = cap_sw_info,
3380352f7f91STakashi Iwai 	.get = cap_sw_get,
3381352f7f91STakashi Iwai 	.put = cap_sw_put,
3382352f7f91STakashi Iwai };
3383352f7f91STakashi Iwai 
3384352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3385352f7f91STakashi Iwai {
3386352f7f91STakashi Iwai 	hda_nid_t nid;
3387352f7f91STakashi Iwai 	int i, depth;
3388352f7f91STakashi Iwai 
3389352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3390352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3391352f7f91STakashi Iwai 		if (depth >= path->depth)
3392352f7f91STakashi Iwai 			return -EINVAL;
3393352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3394352f7f91STakashi Iwai 		nid = path->path[i];
3395352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3396352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3397352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3398352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3399352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3400352f7f91STakashi Iwai 				int idx = path->idx[i];
3401352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3402352f7f91STakashi Iwai 					idx = 0;
3403352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3404352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3405352f7f91STakashi Iwai 			}
3406352f7f91STakashi Iwai 		}
3407352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3408352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3409352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3410352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3411352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3412352f7f91STakashi Iwai 				int idx = path->idx[i];
3413352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3414352f7f91STakashi Iwai 					idx = 0;
3415352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3416352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3417352f7f91STakashi Iwai 			}
3418352f7f91STakashi Iwai 		}
3419352f7f91STakashi Iwai 	}
3420352f7f91STakashi Iwai 	return 0;
3421352f7f91STakashi Iwai }
3422352f7f91STakashi Iwai 
3423352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3424352f7f91STakashi Iwai {
3425352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3426352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3427352f7f91STakashi Iwai 	unsigned int val;
3428352f7f91STakashi Iwai 	int i;
3429352f7f91STakashi Iwai 
3430352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3431352f7f91STakashi Iwai 		return false;
3432352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3433352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3434352f7f91STakashi Iwai 			continue;
3435352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3436352f7f91STakashi Iwai 			return false;
3437352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3438352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3439352f7f91STakashi Iwai 	}
3440352f7f91STakashi Iwai 	return false;
3441352f7f91STakashi Iwai }
3442352f7f91STakashi Iwai 
3443a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3444a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3445a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3446a35bd1e3STakashi Iwai {
3447a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3448a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3449a35bd1e3STakashi Iwai 	int ret;
3450a35bd1e3STakashi Iwai 
3451a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3452a35bd1e3STakashi Iwai 	if (ret < 0)
3453a35bd1e3STakashi Iwai 		return ret;
3454a35bd1e3STakashi Iwai 
3455a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
34567fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3457a35bd1e3STakashi Iwai 
3458a35bd1e3STakashi Iwai 	return ret;
3459a35bd1e3STakashi Iwai }
3460a35bd1e3STakashi Iwai 
3461352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3462352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3463352f7f91STakashi Iwai 			      bool inv_dmic)
3464352f7f91STakashi Iwai {
3465352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3466975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3467352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3468352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3469352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3470a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3471352f7f91STakashi Iwai 
3472352f7f91STakashi Iwai 	if (!ctl)
3473352f7f91STakashi Iwai 		return 0;
3474352f7f91STakashi Iwai 
3475352f7f91STakashi Iwai 	if (label)
3476352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3477352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3478352f7f91STakashi Iwai 	else
3479352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3480352f7f91STakashi Iwai 			 "Capture %s", sfx);
3481a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3482352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3483a35bd1e3STakashi Iwai 	if (!knew)
3484a35bd1e3STakashi Iwai 		return -ENOMEM;
3485a90229e0STakashi Iwai 	if (is_switch)
3486a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3487a35bd1e3STakashi Iwai 	if (!inv_dmic)
3488a35bd1e3STakashi Iwai 		return 0;
3489352f7f91STakashi Iwai 
3490352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3491352f7f91STakashi Iwai 	if (label)
3492352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3493352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3494352f7f91STakashi Iwai 	else
3495352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3496352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3497a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3498352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3499a35bd1e3STakashi Iwai 	if (!knew)
3500a35bd1e3STakashi Iwai 		return -ENOMEM;
3501a90229e0STakashi Iwai 	if (is_switch)
3502a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3503a35bd1e3STakashi Iwai 	return 0;
3504352f7f91STakashi Iwai }
3505352f7f91STakashi Iwai 
3506352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3507352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3508352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3509352f7f91STakashi Iwai 				     bool inv_dmic)
3510352f7f91STakashi Iwai {
3511352f7f91STakashi Iwai 	int err;
3512352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3513352f7f91STakashi Iwai 	if (err < 0)
3514352f7f91STakashi Iwai 		return err;
3515352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3516071c73adSTakashi Iwai 	if (err < 0)
3517071c73adSTakashi Iwai 		return err;
3518071c73adSTakashi Iwai 	return 0;
35191da177e4SLinus Torvalds }
3520071c73adSTakashi Iwai 
3521352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3522352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3523352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3524352f7f91STakashi Iwai {
3525352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3526352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3527352f7f91STakashi Iwai 
3528352f7f91STakashi Iwai 	if (vol_ctl) {
352912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3530352f7f91STakashi Iwai 		if (!knew)
3531352f7f91STakashi Iwai 			return -ENOMEM;
3532352f7f91STakashi Iwai 		knew->index = idx;
3533352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3534352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3535352f7f91STakashi Iwai 	}
3536352f7f91STakashi Iwai 	if (sw_ctl) {
353712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3538352f7f91STakashi Iwai 		if (!knew)
3539352f7f91STakashi Iwai 			return -ENOMEM;
3540352f7f91STakashi Iwai 		knew->index = idx;
3541352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3542352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3543352f7f91STakashi Iwai 	}
3544352f7f91STakashi Iwai 	return 0;
3545352f7f91STakashi Iwai }
3546352f7f91STakashi Iwai 
3547352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3548352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3549352f7f91STakashi Iwai {
3550352f7f91STakashi Iwai 	struct nid_path *path;
3551352f7f91STakashi Iwai 	unsigned int ctl;
3552352f7f91STakashi Iwai 	int i;
3553352f7f91STakashi Iwai 
3554c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3555352f7f91STakashi Iwai 	if (!path)
3556352f7f91STakashi Iwai 		return 0;
3557352f7f91STakashi Iwai 	ctl = path->ctls[type];
3558352f7f91STakashi Iwai 	if (!ctl)
3559352f7f91STakashi Iwai 		return 0;
3560352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3561c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3562352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3563352f7f91STakashi Iwai 			return 0;
3564352f7f91STakashi Iwai 	}
3565352f7f91STakashi Iwai 	return ctl;
3566352f7f91STakashi Iwai }
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3569352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3570352f7f91STakashi Iwai {
3571352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3572352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3573c970042cSTakashi Iwai 	int i, err, type;
3574352f7f91STakashi Iwai 
3575352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3576352f7f91STakashi Iwai 		bool inv_dmic;
3577c970042cSTakashi Iwai 		int idx;
35789dba205bSTakashi Iwai 
3579c970042cSTakashi Iwai 		idx = imux->items[i].index;
3580c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
35819dba205bSTakashi Iwai 			continue;
3582352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3583352f7f91STakashi Iwai 
3584352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3585c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3586c970042cSTakashi Iwai 						 spec->input_labels[idx],
3587c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3588c970042cSTakashi Iwai 						 type,
3589352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3590352f7f91STakashi Iwai 						 inv_dmic);
3591d13bd412STakashi Iwai 			if (err < 0)
3592071c73adSTakashi Iwai 				return err;
3593352f7f91STakashi Iwai 		}
3594352f7f91STakashi Iwai 	}
3595071c73adSTakashi Iwai 	return 0;
3596352f7f91STakashi Iwai }
3597071c73adSTakashi Iwai 
3598352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3599352f7f91STakashi Iwai {
3600352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3601352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3602352f7f91STakashi Iwai 	int i, n, nums, err;
3603352f7f91STakashi Iwai 
3604352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3605352f7f91STakashi Iwai 		nums = 1;
3606352f7f91STakashi Iwai 	else
3607352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3608352f7f91STakashi Iwai 
3609352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3610352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3611624d914dSTakashi Iwai 		const char *name;
3612624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3613624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3614352f7f91STakashi Iwai 		if (!knew)
3615352f7f91STakashi Iwai 			return -ENOMEM;
3616352f7f91STakashi Iwai 		knew->count = nums;
3617352f7f91STakashi Iwai 	}
3618352f7f91STakashi Iwai 
3619352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3620352f7f91STakashi Iwai 		bool multi = false;
362199a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3622352f7f91STakashi Iwai 		bool inv_dmic = false;
3623352f7f91STakashi Iwai 		int vol, sw;
3624352f7f91STakashi Iwai 
3625352f7f91STakashi Iwai 		vol = sw = 0;
3626352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3627352f7f91STakashi Iwai 			struct nid_path *path;
3628c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3629352f7f91STakashi Iwai 			if (!path)
3630352f7f91STakashi Iwai 				continue;
3631352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3632352f7f91STakashi Iwai 			if (!vol)
3633352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
363499a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3635352f7f91STakashi Iwai 				multi = true;
363699a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
363799a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
363899a5592dSDavid Henningsson 					multi_cap_vol = true;
363999a5592dSDavid Henningsson 			}
3640352f7f91STakashi Iwai 			if (!sw)
3641352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
364299a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3643352f7f91STakashi Iwai 				multi = true;
364499a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
364599a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
364699a5592dSDavid Henningsson 					multi_cap_vol = true;
364799a5592dSDavid Henningsson 			}
3648352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3649352f7f91STakashi Iwai 				inv_dmic = true;
3650352f7f91STakashi Iwai 		}
3651352f7f91STakashi Iwai 
3652352f7f91STakashi Iwai 		if (!multi)
3653352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3654352f7f91STakashi Iwai 							inv_dmic);
3655ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3656352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3657352f7f91STakashi Iwai 		else
3658352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3659d13bd412STakashi Iwai 		if (err < 0)
3660071c73adSTakashi Iwai 			return err;
3661071c73adSTakashi Iwai 	}
3662071c73adSTakashi Iwai 
36631da177e4SLinus Torvalds 	return 0;
36641da177e4SLinus Torvalds }
36651da177e4SLinus Torvalds 
3666352f7f91STakashi Iwai /*
3667352f7f91STakashi Iwai  * add mic boosts if needed
3668352f7f91STakashi Iwai  */
36696f7c83afSTakashi Iwai 
36706f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
36716f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
36726f7c83afSTakashi Iwai 			    int dir, int idx)
36736f7c83afSTakashi Iwai {
36746f7c83afSTakashi Iwai 	unsigned int step;
36756f7c83afSTakashi Iwai 
36766f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
36776f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
36786f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
36796f7c83afSTakashi Iwai 		return false;
36806f7c83afSTakashi Iwai 
36816f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
36826f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
36836f7c83afSTakashi Iwai 	if (step < 0x20)
36846f7c83afSTakashi Iwai 		return false;
36856f7c83afSTakashi Iwai 	return true;
36866f7c83afSTakashi Iwai }
36876f7c83afSTakashi Iwai 
36886f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
36896f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
36906f7c83afSTakashi Iwai 				       struct nid_path *path)
36916f7c83afSTakashi Iwai {
36926f7c83afSTakashi Iwai 	unsigned int val = 0;
36936f7c83afSTakashi Iwai 	hda_nid_t nid;
36946f7c83afSTakashi Iwai 	int depth;
36956f7c83afSTakashi Iwai 
36966f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
36976f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
36986f7c83afSTakashi Iwai 			break;
36996f7c83afSTakashi Iwai 		nid = path->path[depth];
37006f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
37016f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
37026f7c83afSTakashi Iwai 			break;
37036f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
37046f7c83afSTakashi Iwai 					   path->idx[depth])) {
37056f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
37066f7c83afSTakashi Iwai 						  HDA_INPUT);
37076f7c83afSTakashi Iwai 			break;
37086f7c83afSTakashi Iwai 		}
37096f7c83afSTakashi Iwai 	}
37106f7c83afSTakashi Iwai 
37116f7c83afSTakashi Iwai 	return val;
37126f7c83afSTakashi Iwai }
37136f7c83afSTakashi Iwai 
3714352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3715352f7f91STakashi Iwai {
3716352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3717352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
37186f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3719a35bd1e3STakashi Iwai 	int i;
3720352f7f91STakashi Iwai 
37216f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
37226f7c83afSTakashi Iwai 		return 0;
37236f7c83afSTakashi Iwai 
37246f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3725352f7f91STakashi Iwai 		struct nid_path *path;
3726352f7f91STakashi Iwai 		unsigned int val;
37276f7c83afSTakashi Iwai 		int idx;
3728975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3729352f7f91STakashi Iwai 
37306f7c83afSTakashi Iwai 		idx = imux->items[i].index;
37316f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
373202aba550SDavid Henningsson 			continue;
373302aba550SDavid Henningsson 
37346f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
37351799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
37366f7c83afSTakashi Iwai 			continue;
37376f7c83afSTakashi Iwai 
37386f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
37396f7c83afSTakashi Iwai 		if (!path)
37406f7c83afSTakashi Iwai 			continue;
37416f7c83afSTakashi Iwai 
37426f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
37436f7c83afSTakashi Iwai 		if (!val)
37446f7c83afSTakashi Iwai 			continue;
37456f7c83afSTakashi Iwai 
37466f7c83afSTakashi Iwai 		/* create a boost control */
3747352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
37486f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3749a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3750a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3751a35bd1e3STakashi Iwai 			return -ENOMEM;
3752352f7f91STakashi Iwai 
3753352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3754352f7f91STakashi Iwai 	}
3755352f7f91STakashi Iwai 	return 0;
3756352f7f91STakashi Iwai }
3757352f7f91STakashi Iwai 
3758352f7f91STakashi Iwai /*
3759352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3760352f7f91STakashi Iwai  */
3761352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3762352f7f91STakashi Iwai {
3763352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
37640c8c0f56STakashi Iwai 	struct nid_path *path;
3765352f7f91STakashi Iwai 	int i, nums;
37662c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3767352f7f91STakashi Iwai 
3768352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3769352f7f91STakashi Iwai 	nums = 0;
3770352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
37712c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3772352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3773352f7f91STakashi Iwai 		if (!dig_nid)
3774352f7f91STakashi Iwai 			continue;
37753ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
37760c8c0f56STakashi Iwai 		if (!path)
3777352f7f91STakashi Iwai 			continue;
37784e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
3779e1284af7STakashi Iwai 		path->active = true;
3780196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
37812c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3782352f7f91STakashi Iwai 		if (!nums) {
3783352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3784352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3785352f7f91STakashi Iwai 		} else {
3786352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3787352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3788352f7f91STakashi Iwai 				break;
3789352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3790352f7f91STakashi Iwai 		}
3791352f7f91STakashi Iwai 		nums++;
3792352f7f91STakashi Iwai 	}
3793352f7f91STakashi Iwai 
3794352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
37952c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3796352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3797352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3798352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3799352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3800352f7f91STakashi Iwai 				continue;
3801352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3802352f7f91STakashi Iwai 				continue;
38032c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3804352f7f91STakashi Iwai 			if (path) {
38054e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
3806352f7f91STakashi Iwai 				path->active = true;
3807352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
38082430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
38092c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3810352f7f91STakashi Iwai 				break;
3811352f7f91STakashi Iwai 			}
3812352f7f91STakashi Iwai 		}
3813352f7f91STakashi Iwai 	}
3814352f7f91STakashi Iwai }
3815352f7f91STakashi Iwai 
38161da177e4SLinus Torvalds 
38171da177e4SLinus Torvalds /*
3818352f7f91STakashi Iwai  * input MUX handling
38191da177e4SLinus Torvalds  */
38201da177e4SLinus Torvalds 
3821352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3822352f7f91STakashi Iwai 
3823352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3824352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3825352f7f91STakashi Iwai 		      unsigned int idx)
3826352f7f91STakashi Iwai {
3827352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3828352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
382955196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3830352f7f91STakashi Iwai 
3831352f7f91STakashi Iwai 	imux = &spec->input_mux;
3832352f7f91STakashi Iwai 	if (!imux->num_items)
38331da177e4SLinus Torvalds 		return 0;
38341da177e4SLinus Torvalds 
3835352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3836352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3837352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3838352f7f91STakashi Iwai 		return 0;
3839352f7f91STakashi Iwai 
384055196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
384155196fffSTakashi Iwai 	if (!old_path)
3842352f7f91STakashi Iwai 		return 0;
384355196fffSTakashi Iwai 	if (old_path->active)
384455196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3845352f7f91STakashi Iwai 
3846352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3847352f7f91STakashi Iwai 
3848967303daSTakashi Iwai 	if (spec->hp_mic)
3849967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3850352f7f91STakashi Iwai 
3851352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3852352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3853352f7f91STakashi Iwai 
3854c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3855352f7f91STakashi Iwai 	if (!path)
3856352f7f91STakashi Iwai 		return 0;
3857352f7f91STakashi Iwai 	if (path->active)
3858352f7f91STakashi Iwai 		return 0;
3859352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3860352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
38617fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
386255196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
38631da177e4SLinus Torvalds 	return 1;
38641da177e4SLinus Torvalds }
38651da177e4SLinus Torvalds 
38661da177e4SLinus Torvalds 
38671da177e4SLinus Torvalds /*
3868352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
38691da177e4SLinus Torvalds  */
3870352f7f91STakashi Iwai 
3871352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3872352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
38731da177e4SLinus Torvalds {
387460ea8ca2STakashi Iwai 	int i;
387560ea8ca2STakashi Iwai 	bool present = false;
38761da177e4SLinus Torvalds 
3877352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3878352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3879352f7f91STakashi Iwai 		if (!nid)
3880352f7f91STakashi Iwai 			break;
38810b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
38820b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
38830b4df931STakashi Iwai 			continue;
388460ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
388560ea8ca2STakashi Iwai 			present = true;
38861da177e4SLinus Torvalds 	}
3887352f7f91STakashi Iwai 	return present;
38881da177e4SLinus Torvalds }
38891da177e4SLinus Torvalds 
3890352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3891352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3892e80c60f3STakashi Iwai 			int *paths, bool mute)
38931da177e4SLinus Torvalds {
3894352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3895352f7f91STakashi Iwai 	int i;
38961da177e4SLinus Torvalds 
3897352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3898352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3899967303daSTakashi Iwai 		unsigned int val, oldval;
3900352f7f91STakashi Iwai 		if (!nid)
3901352f7f91STakashi Iwai 			break;
39027eebffd3STakashi Iwai 
39037eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
3904e80c60f3STakashi Iwai 			struct nid_path *path;
3905e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
3906e80c60f3STakashi Iwai 
3907e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
3908e80c60f3STakashi Iwai 			if (!path)
3909e80c60f3STakashi Iwai 				continue;
3910e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
3911e80c60f3STakashi Iwai 			if (!mute_nid)
3912e80c60f3STakashi Iwai 				continue;
39137eebffd3STakashi Iwai 			if (mute)
3914e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
39157eebffd3STakashi Iwai 			else
3916e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
39177eebffd3STakashi Iwai 			set_pin_eapd(codec, nid, !mute);
39187eebffd3STakashi Iwai 			continue;
39197eebffd3STakashi Iwai 		}
39207eebffd3STakashi Iwai 
3921967303daSTakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
3922967303daSTakashi Iwai 		if (oldval & PIN_IN)
3923967303daSTakashi Iwai 			continue; /* no mute for inputs */
3924352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3925352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3926352f7f91STakashi Iwai 		 */
39272c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
3928967303daSTakashi Iwai 			val = oldval & ~PIN_HP;
39292c12c30dSTakashi Iwai 		else
3930352f7f91STakashi Iwai 			val = 0;
39312c12c30dSTakashi Iwai 		if (!mute)
3932967303daSTakashi Iwai 			val |= oldval;
39332c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
39342c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
39352c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
39362c12c30dSTakashi Iwai 		 * init / resume again
39372c12c30dSTakashi Iwai 		 */
39382c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3939d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3940352f7f91STakashi Iwai 	}
3941352f7f91STakashi Iwai }
39421da177e4SLinus Torvalds 
3943dda42bd0STakashi Iwai /**
3944dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
3945dda42bd0STakashi Iwai  * @codec: the HDA codec
3946dda42bd0STakashi Iwai  *
3947dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
3948dda42bd0STakashi Iwai  */
39495d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3950352f7f91STakashi Iwai {
3951352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3952e80c60f3STakashi Iwai 	int *paths;
3953352f7f91STakashi Iwai 	int on;
3954352f7f91STakashi Iwai 
3955352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3956352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3957352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3958352f7f91STakashi Iwai 	 */
3959e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3960e80c60f3STakashi Iwai 		paths = spec->out_paths;
3961e80c60f3STakashi Iwai 	else
3962e80c60f3STakashi Iwai 		paths = spec->hp_paths;
3963352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3964e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
3965352f7f91STakashi Iwai 
3966352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3967352f7f91STakashi Iwai 		on = 0;
3968352f7f91STakashi Iwai 	else
3969352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3970352f7f91STakashi Iwai 	on |= spec->master_mute;
397147b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3972e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3973e80c60f3STakashi Iwai 		paths = spec->out_paths;
3974e80c60f3STakashi Iwai 	else
3975e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
3976352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
3977e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
3978352f7f91STakashi Iwai 
3979352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3980352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3981352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3982352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3983352f7f91STakashi Iwai 		return;
3984352f7f91STakashi Iwai 	if (!spec->automute_lo)
3985352f7f91STakashi Iwai 		on = 0;
3986352f7f91STakashi Iwai 	else
3987352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3988352f7f91STakashi Iwai 	on |= spec->master_mute;
398947b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3990e80c60f3STakashi Iwai 	paths = spec->out_paths;
3991352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3992e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
3993352f7f91STakashi Iwai }
39942698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
3995352f7f91STakashi Iwai 
3996352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3997352f7f91STakashi Iwai {
3998352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3999352f7f91STakashi Iwai 	if (spec->automute_hook)
4000352f7f91STakashi Iwai 		spec->automute_hook(codec);
4001352f7f91STakashi Iwai 	else
40025d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
40037eebffd3STakashi Iwai 
40047eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
40057eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
40067eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4007352f7f91STakashi Iwai }
4008352f7f91STakashi Iwai 
4009dda42bd0STakashi Iwai /**
4010dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4011dda42bd0STakashi Iwai  * @codec: the HDA codec
4012dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4013dda42bd0STakashi Iwai  */
40141a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
40151a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4016352f7f91STakashi Iwai {
4017352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
401892603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
401992603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4020352f7f91STakashi Iwai 
402192603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
402292603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
402392603c59STakashi Iwai 		pins++;
402492603c59STakashi Iwai 		num_pins--;
402592603c59STakashi Iwai 	}
402692603c59STakashi Iwai 
402792603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4028352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4029352f7f91STakashi Iwai 		return;
4030352f7f91STakashi Iwai 	call_update_outputs(codec);
4031352f7f91STakashi Iwai }
40322698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4033352f7f91STakashi Iwai 
4034dda42bd0STakashi Iwai /**
4035dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4036dda42bd0STakashi Iwai  * @codec: the HDA codec
4037dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4038dda42bd0STakashi Iwai  */
40391a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
40401a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4041352f7f91STakashi Iwai {
4042352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4043352f7f91STakashi Iwai 
4044352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4045352f7f91STakashi Iwai 		return;
4046352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4047352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4048352f7f91STakashi Iwai 		return;
4049352f7f91STakashi Iwai 
4050352f7f91STakashi Iwai 	spec->line_jack_present =
4051352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4052352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4053352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4054352f7f91STakashi Iwai 		return;
4055352f7f91STakashi Iwai 	call_update_outputs(codec);
4056352f7f91STakashi Iwai }
40572698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4058352f7f91STakashi Iwai 
4059dda42bd0STakashi Iwai /**
4060dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4061dda42bd0STakashi Iwai  * @codec: the HDA codec
4062dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4063dda42bd0STakashi Iwai  */
40641a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
40651a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4066352f7f91STakashi Iwai {
4067352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4068352f7f91STakashi Iwai 	int i;
4069352f7f91STakashi Iwai 
4070352f7f91STakashi Iwai 	if (!spec->auto_mic)
4071352f7f91STakashi Iwai 		return;
4072352f7f91STakashi Iwai 
4073352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
40740b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
40750b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
40760b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
40770b4df931STakashi Iwai 			continue;
407860ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4079352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4080352f7f91STakashi Iwai 			return;
4081352f7f91STakashi Iwai 		}
4082352f7f91STakashi Iwai 	}
4083352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
40841da177e4SLinus Torvalds }
40852698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
40861da177e4SLinus Torvalds 
408777afe0e9STakashi Iwai /* call appropriate hooks */
40881a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
40891a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
409077afe0e9STakashi Iwai {
409177afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
409277afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
409377afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
409477afe0e9STakashi Iwai 	else
409577afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
409677afe0e9STakashi Iwai }
409777afe0e9STakashi Iwai 
409877afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
40991a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
410077afe0e9STakashi Iwai {
410177afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
410277afe0e9STakashi Iwai 	if (spec->line_automute_hook)
410377afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
410477afe0e9STakashi Iwai 	else
410577afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
410677afe0e9STakashi Iwai }
410777afe0e9STakashi Iwai 
410877afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
41091a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
411077afe0e9STakashi Iwai {
411177afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
411277afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
411377afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
411477afe0e9STakashi Iwai 	else
411577afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
411677afe0e9STakashi Iwai }
411777afe0e9STakashi Iwai 
4118963afde9STakashi Iwai /* update jack retasking */
4119963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4120963afde9STakashi Iwai {
4121963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4122963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4123963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4124963afde9STakashi Iwai }
4125963afde9STakashi Iwai 
41261da177e4SLinus Torvalds /*
4127352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
41281da177e4SLinus Torvalds  */
4129352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4130352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4131352f7f91STakashi Iwai {
4132352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4133352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4134352f7f91STakashi Iwai 	static const char * const texts3[] = {
4135352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
41361da177e4SLinus Torvalds 	};
41371da177e4SLinus Torvalds 
4138352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4139352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4140352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4141352f7f91STakashi Iwai }
4142352f7f91STakashi Iwai 
4143352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4144352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4145352f7f91STakashi Iwai {
4146352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4147352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4148352f7f91STakashi Iwai 	unsigned int val = 0;
4149352f7f91STakashi Iwai 	if (spec->automute_speaker)
4150352f7f91STakashi Iwai 		val++;
4151352f7f91STakashi Iwai 	if (spec->automute_lo)
4152352f7f91STakashi Iwai 		val++;
4153352f7f91STakashi Iwai 
4154352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4155352f7f91STakashi Iwai 	return 0;
4156352f7f91STakashi Iwai }
4157352f7f91STakashi Iwai 
4158352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4159352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4160352f7f91STakashi Iwai {
4161352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4162352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4163352f7f91STakashi Iwai 
4164352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4165352f7f91STakashi Iwai 	case 0:
4166352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4167352f7f91STakashi Iwai 			return 0;
4168352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4169352f7f91STakashi Iwai 		spec->automute_lo = 0;
4170352f7f91STakashi Iwai 		break;
4171352f7f91STakashi Iwai 	case 1:
4172352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4173352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4174352f7f91STakashi Iwai 				return 0;
4175352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4176352f7f91STakashi Iwai 			spec->automute_lo = 0;
4177352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4178352f7f91STakashi Iwai 			if (spec->automute_lo)
4179352f7f91STakashi Iwai 				return 0;
4180352f7f91STakashi Iwai 			spec->automute_lo = 1;
4181352f7f91STakashi Iwai 		} else
4182352f7f91STakashi Iwai 			return -EINVAL;
4183352f7f91STakashi Iwai 		break;
4184352f7f91STakashi Iwai 	case 2:
4185352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4186352f7f91STakashi Iwai 			return -EINVAL;
4187352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4188352f7f91STakashi Iwai 			return 0;
4189352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4190352f7f91STakashi Iwai 		spec->automute_lo = 1;
4191352f7f91STakashi Iwai 		break;
4192352f7f91STakashi Iwai 	default:
4193352f7f91STakashi Iwai 		return -EINVAL;
4194352f7f91STakashi Iwai 	}
4195352f7f91STakashi Iwai 	call_update_outputs(codec);
4196352f7f91STakashi Iwai 	return 1;
4197352f7f91STakashi Iwai }
4198352f7f91STakashi Iwai 
4199352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4200352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4201352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4202352f7f91STakashi Iwai 	.info = automute_mode_info,
4203352f7f91STakashi Iwai 	.get = automute_mode_get,
4204352f7f91STakashi Iwai 	.put = automute_mode_put,
4205352f7f91STakashi Iwai };
4206352f7f91STakashi Iwai 
4207352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4208352f7f91STakashi Iwai {
4209352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4210352f7f91STakashi Iwai 
421112c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4212352f7f91STakashi Iwai 		return -ENOMEM;
4213352f7f91STakashi Iwai 	return 0;
4214352f7f91STakashi Iwai }
4215352f7f91STakashi Iwai 
4216352f7f91STakashi Iwai /*
4217352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4218352f7f91STakashi Iwai  * Set up appropriately if really supported
4219352f7f91STakashi Iwai  */
4220352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4221352f7f91STakashi Iwai {
4222352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4223352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4224352f7f91STakashi Iwai 	int present = 0;
4225352f7f91STakashi Iwai 	int i, err;
4226352f7f91STakashi Iwai 
4227f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4228f72706beSTakashi Iwai 		return 0;
4229f72706beSTakashi Iwai 
4230352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4231352f7f91STakashi Iwai 		present++;
4232352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4233352f7f91STakashi Iwai 		present++;
4234352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4235352f7f91STakashi Iwai 		present++;
4236352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4237352f7f91STakashi Iwai 		return 0;
4238352f7f91STakashi Iwai 
4239352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4240352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4241352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4242352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4243352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4244352f7f91STakashi Iwai 	}
4245352f7f91STakashi Iwai 
4246352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4247352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4248352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4249352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4250352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4251352f7f91STakashi Iwai 	}
4252352f7f91STakashi Iwai 
4253352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4254352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4255352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4256352f7f91STakashi Iwai 			continue;
42574e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
425862f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
425977afe0e9STakashi Iwai 						    call_hp_automute);
4260352f7f91STakashi Iwai 		spec->detect_hp = 1;
4261352f7f91STakashi Iwai 	}
4262352f7f91STakashi Iwai 
4263352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4264352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4265352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4266352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4267352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4268352f7f91STakashi Iwai 					continue;
42694e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4270352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
427177afe0e9STakashi Iwai 								    call_line_automute);
4272352f7f91STakashi Iwai 				spec->detect_lo = 1;
4273352f7f91STakashi Iwai 			}
4274352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4275352f7f91STakashi Iwai 	}
4276352f7f91STakashi Iwai 
4277352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4278352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4279352f7f91STakashi Iwai 
4280352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4281352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4282352f7f91STakashi Iwai 
4283352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4284352f7f91STakashi Iwai 		/* create a control for automute mode */
4285352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4286352f7f91STakashi Iwai 		if (err < 0)
4287352f7f91STakashi Iwai 			return err;
4288352f7f91STakashi Iwai 	}
4289352f7f91STakashi Iwai 	return 0;
4290352f7f91STakashi Iwai }
4291352f7f91STakashi Iwai 
4292352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4293352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4294352f7f91STakashi Iwai {
4295352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4296352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4297352f7f91STakashi Iwai 	int i;
4298352f7f91STakashi Iwai 
4299352f7f91STakashi Iwai 	imux = &spec->input_mux;
4300352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4301352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4302352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4303352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4304352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4305352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4306352f7f91STakashi Iwai 	}
4307352f7f91STakashi Iwai 
4308352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4309352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4310352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4311352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
431277afe0e9STakashi Iwai 						    call_mic_autoswitch);
4313352f7f91STakashi Iwai 	return true;
4314352f7f91STakashi Iwai }
4315352f7f91STakashi Iwai 
4316352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4317352f7f91STakashi Iwai {
4318352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4319352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4320352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4321352f7f91STakashi Iwai }
4322352f7f91STakashi Iwai 
4323352f7f91STakashi Iwai /*
4324352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4325352f7f91STakashi Iwai  * Set up if really supported
4326352f7f91STakashi Iwai  */
4327352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4328352f7f91STakashi Iwai {
4329352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4330352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4331352f7f91STakashi Iwai 	unsigned int types;
4332352f7f91STakashi Iwai 	int i, num_pins;
4333352f7f91STakashi Iwai 
4334d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4335d12daf6fSTakashi Iwai 		return 0;
4336d12daf6fSTakashi Iwai 
4337352f7f91STakashi Iwai 	types = 0;
4338352f7f91STakashi Iwai 	num_pins = 0;
4339352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4340352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4341352f7f91STakashi Iwai 		unsigned int attr;
4342352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4343352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4344352f7f91STakashi Iwai 		if (types & (1 << attr))
4345352f7f91STakashi Iwai 			return 0; /* already occupied */
4346352f7f91STakashi Iwai 		switch (attr) {
4347352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4348352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4349352f7f91STakashi Iwai 				return 0; /* invalid type */
4350352f7f91STakashi Iwai 			break;
4351352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4352352f7f91STakashi Iwai 			return 0; /* invalid entry */
4353352f7f91STakashi Iwai 		default:
4354352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4355352f7f91STakashi Iwai 				return 0; /* invalid type */
4356352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4357352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4358352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4359352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4360352f7f91STakashi Iwai 				return 0; /* no unsol support */
4361352f7f91STakashi Iwai 			break;
4362352f7f91STakashi Iwai 		}
4363352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4364352f7f91STakashi Iwai 			return 0;
4365352f7f91STakashi Iwai 		types |= (1 << attr);
4366352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4367352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4368352f7f91STakashi Iwai 		num_pins++;
4369352f7f91STakashi Iwai 	}
4370352f7f91STakashi Iwai 
4371352f7f91STakashi Iwai 	if (num_pins < 2)
4372352f7f91STakashi Iwai 		return 0;
4373352f7f91STakashi Iwai 
4374352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4375352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4376352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4377352f7f91STakashi Iwai 	 */
4378352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4379352f7f91STakashi Iwai 	     compare_attr, NULL);
4380352f7f91STakashi Iwai 
4381352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4382352f7f91STakashi Iwai 		return 0;
4383352f7f91STakashi Iwai 
4384352f7f91STakashi Iwai 	spec->auto_mic = 1;
4385352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4386352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
43874e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4388352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4389352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4390352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4391352f7f91STakashi Iwai 
4392352f7f91STakashi Iwai 	return 0;
4393352f7f91STakashi Iwai }
4394352f7f91STakashi Iwai 
4395dda42bd0STakashi Iwai /**
4396dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4397dda42bd0STakashi Iwai  * into power down
4398dda42bd0STakashi Iwai  * @codec: the HDA codec
4399dda42bd0STakashi Iwai  * @nid: NID to evalute
4400dda42bd0STakashi Iwai  * @power_state: target power state
4401dda42bd0STakashi Iwai  */
4402dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
440355196fffSTakashi Iwai 						  hda_nid_t nid,
440455196fffSTakashi Iwai 						  unsigned int power_state)
440555196fffSTakashi Iwai {
4406dfc6e469STakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->afg)
440755196fffSTakashi Iwai 		return power_state;
440855196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
440955196fffSTakashi Iwai 		return power_state;
4410b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
441155196fffSTakashi Iwai 		return power_state;
441255196fffSTakashi Iwai 	return AC_PWRST_D3;
441355196fffSTakashi Iwai }
4414dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
441555196fffSTakashi Iwai 
4416ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4417ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4418ebb93c05STakashi Iwai {
4419ebb93c05STakashi Iwai 	int i, nums;
4420ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4421ebb93c05STakashi Iwai 	bool has_amp;
4422ebb93c05STakashi Iwai 
4423ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4424ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4425ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4426ebb93c05STakashi Iwai 		if (has_amp)
4427ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, mix,
4428ebb93c05STakashi Iwai 						 HDA_INPUT, i,
4429ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4430ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4431ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, conn[i],
4432ebb93c05STakashi Iwai 						 HDA_OUTPUT, 0,
4433ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4434ebb93c05STakashi Iwai 	}
4435ebb93c05STakashi Iwai }
4436352f7f91STakashi Iwai 
4437dda42bd0STakashi Iwai /**
4438dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
4439dda42bd0STakashi Iwai  * set up the hda_gen_spec
4440dda42bd0STakashi Iwai  * @codec: the HDA codec
4441dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
44429eb413e5STakashi Iwai  *
44439eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4444352f7f91STakashi Iwai  * or a negative error code
4445352f7f91STakashi Iwai  */
4446352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
44479eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4448352f7f91STakashi Iwai {
4449352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4450352f7f91STakashi Iwai 	int err;
4451352f7f91STakashi Iwai 
44521c70a583STakashi Iwai 	parse_user_hints(codec);
44531c70a583STakashi Iwai 
4454e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4455e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4456e4a395e7STakashi Iwai 
44579eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
44589eb413e5STakashi Iwai 		spec->autocfg = *cfg;
44599eb413e5STakashi Iwai 		cfg = &spec->autocfg;
44609eb413e5STakashi Iwai 	}
44619eb413e5STakashi Iwai 
446298bd1115STakashi Iwai 	if (!spec->main_out_badness)
446398bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
446498bd1115STakashi Iwai 	if (!spec->extra_out_badness)
446598bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
446698bd1115STakashi Iwai 
44676fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
44686fc4cb97SDavid Henningsson 
4469352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4470352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4471352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4472352f7f91STakashi Iwai 			spec->no_analog = 1;
4473352f7f91STakashi Iwai 			goto dig_only;
4474352f7f91STakashi Iwai 		}
4475c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4476352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4477352f7f91STakashi Iwai 	}
4478352f7f91STakashi Iwai 
4479352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4480352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4481352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4482352f7f91STakashi Iwai 		/* use HP as primary out */
4483352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4484352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4485352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4486352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4487352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4488352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4489352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4490352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4491352f7f91STakashi Iwai 	}
4492352f7f91STakashi Iwai 
4493352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4494352f7f91STakashi Iwai 	if (err < 0)
4495352f7f91STakashi Iwai 		return err;
4496352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4497352f7f91STakashi Iwai 	if (err < 0)
4498352f7f91STakashi Iwai 		return err;
4499352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4500352f7f91STakashi Iwai 	if (err < 0)
4501352f7f91STakashi Iwai 		return err;
4502352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4503352f7f91STakashi Iwai 	if (err < 0)
4504352f7f91STakashi Iwai 		return err;
4505352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4506352f7f91STakashi Iwai 	if (err < 0)
4507352f7f91STakashi Iwai 		return err;
450838cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
450938cf6f1aSTakashi Iwai 	if (err < 0)
451038cf6f1aSTakashi Iwai 		return err;
4511c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4512c30aa7b2STakashi Iwai 	if (err < 0)
4513c30aa7b2STakashi Iwai 		return err;
4514967303daSTakashi Iwai 	err = create_hp_mic(codec);
4515352f7f91STakashi Iwai 	if (err < 0)
4516352f7f91STakashi Iwai 		return err;
4517352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4518352f7f91STakashi Iwai 	if (err < 0)
4519352f7f91STakashi Iwai 		return err;
4520352f7f91STakashi Iwai 
4521a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4522a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4523a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4524a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4525a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4526a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4527a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4528a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4529352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4530352f7f91STakashi Iwai 					  spec->const_channel_count);
4531352f7f91STakashi Iwai 
4532352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4533352f7f91STakashi Iwai 	if (err < 0)
4534352f7f91STakashi Iwai 		return err;
4535352f7f91STakashi Iwai 
4536352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4537352f7f91STakashi Iwai 	if (err < 0)
4538352f7f91STakashi Iwai 		return err;
4539352f7f91STakashi Iwai 
4540352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4541352f7f91STakashi Iwai 	if (err < 0)
4542352f7f91STakashi Iwai 		return err;
4543352f7f91STakashi Iwai 
4544f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
4545f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
454674f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
454774f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
4548f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
4549f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
4550f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
4551f1e762ddSTakashi Iwai 		if (err < 0)
4552f1e762ddSTakashi Iwai 			return err;
4553f1e762ddSTakashi Iwai 	}
4554f1e762ddSTakashi Iwai 
4555f1e762ddSTakashi Iwai 
4556352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4557352f7f91STakashi Iwai 	if (err < 0)
4558352f7f91STakashi Iwai 		return err;
4559352f7f91STakashi Iwai 
4560352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4561352f7f91STakashi Iwai 	if (err < 0)
4562352f7f91STakashi Iwai 		return err;
4563352f7f91STakashi Iwai 
4564ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4565ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4566ced4cefcSTakashi Iwai 	 */
4567ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4568ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4569ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4570ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4571ced4cefcSTakashi Iwai 		if (err < 0)
4572ced4cefcSTakashi Iwai 			return err;
4573ced4cefcSTakashi Iwai 	}
4574ced4cefcSTakashi Iwai 
4575f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4576978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4577978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4578978e77e7STakashi Iwai 						    cfg->line_out_pins);
4579978e77e7STakashi Iwai 			if (err < 0)
4580978e77e7STakashi Iwai 				return err;
4581978e77e7STakashi Iwai 		}
4582978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4583978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4584978e77e7STakashi Iwai 						    cfg->hp_pins);
4585978e77e7STakashi Iwai 			if (err < 0)
4586978e77e7STakashi Iwai 				return err;
4587978e77e7STakashi Iwai 		}
4588978e77e7STakashi Iwai 	}
4589978e77e7STakashi Iwai 
4590ebb93c05STakashi Iwai 	/* mute all aamix input initially */
4591ebb93c05STakashi Iwai 	if (spec->mixer_nid)
4592ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
4593ebb93c05STakashi Iwai 
4594352f7f91STakashi Iwai  dig_only:
4595352f7f91STakashi Iwai 	parse_digital(codec);
4596352f7f91STakashi Iwai 
459755196fffSTakashi Iwai 	if (spec->power_down_unused)
459855196fffSTakashi Iwai 		codec->power_filter = snd_hda_gen_path_power_filter;
459955196fffSTakashi Iwai 
46007504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
46017504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
46027504b6cdSTakashi Iwai 		if (err < 0)
46037504b6cdSTakashi Iwai 			return err;
46047504b6cdSTakashi Iwai 	}
46057504b6cdSTakashi Iwai 
4606352f7f91STakashi Iwai 	return 1;
4607352f7f91STakashi Iwai }
46082698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
4609352f7f91STakashi Iwai 
4610352f7f91STakashi Iwai 
4611352f7f91STakashi Iwai /*
4612352f7f91STakashi Iwai  * Build control elements
4613352f7f91STakashi Iwai  */
4614352f7f91STakashi Iwai 
4615352f7f91STakashi Iwai /* slave controls for virtual master */
4616352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4617352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4618352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4619352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4620ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4621ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
462203ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
4623352f7f91STakashi Iwai 	NULL,
4624352f7f91STakashi Iwai };
4625352f7f91STakashi Iwai 
4626dda42bd0STakashi Iwai /**
4627dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
4628dda42bd0STakashi Iwai  * @codec: the HDA codec
4629dda42bd0STakashi Iwai  *
4630dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
4631dda42bd0STakashi Iwai  */
4632352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
4633352f7f91STakashi Iwai {
4634352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4635352f7f91STakashi Iwai 	int err;
4636352f7f91STakashi Iwai 
463736502d02STakashi Iwai 	if (spec->kctls.used) {
4638352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
4639352f7f91STakashi Iwai 		if (err < 0)
4640352f7f91STakashi Iwai 			return err;
464136502d02STakashi Iwai 	}
4642352f7f91STakashi Iwai 
4643352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
4644352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
4645352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4646352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4647bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
4648352f7f91STakashi Iwai 		if (err < 0)
4649352f7f91STakashi Iwai 			return err;
4650352f7f91STakashi Iwai 		if (!spec->no_analog) {
4651352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
4652352f7f91STakashi Iwai 							    &spec->multiout);
4653352f7f91STakashi Iwai 			if (err < 0)
4654352f7f91STakashi Iwai 				return err;
4655352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
4656352f7f91STakashi Iwai 		}
4657352f7f91STakashi Iwai 	}
4658352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
4659352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
4660352f7f91STakashi Iwai 		if (err < 0)
4661352f7f91STakashi Iwai 			return err;
4662352f7f91STakashi Iwai 	}
4663352f7f91STakashi Iwai 
4664352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
4665352f7f91STakashi Iwai 	if (!spec->no_analog &&
4666352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
4667352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
46687a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
4669352f7f91STakashi Iwai 					  "Playback Volume");
4670352f7f91STakashi Iwai 		if (err < 0)
4671352f7f91STakashi Iwai 			return err;
4672352f7f91STakashi Iwai 	}
4673352f7f91STakashi Iwai 	if (!spec->no_analog &&
4674352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
4675352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
4676352f7f91STakashi Iwai 					    NULL, slave_pfxs,
4677352f7f91STakashi Iwai 					    "Playback Switch",
4678352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
4679352f7f91STakashi Iwai 		if (err < 0)
4680352f7f91STakashi Iwai 			return err;
4681b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
4682fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
4683fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
4684b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4685b63eae0aSTakashi Iwai 		}
4686352f7f91STakashi Iwai 	}
4687352f7f91STakashi Iwai 
4688352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
4689352f7f91STakashi Iwai 
4690352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
4691352f7f91STakashi Iwai 	if (err < 0)
4692352f7f91STakashi Iwai 		return err;
4693352f7f91STakashi Iwai 
4694352f7f91STakashi Iwai 	return 0;
4695352f7f91STakashi Iwai }
46962698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
4697352f7f91STakashi Iwai 
4698352f7f91STakashi Iwai 
4699352f7f91STakashi Iwai /*
4700352f7f91STakashi Iwai  * PCM definitions
4701352f7f91STakashi Iwai  */
4702352f7f91STakashi Iwai 
4703e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
4704e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
4705e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
4706e6b85f3cSTakashi Iwai 				   int action)
4707e6b85f3cSTakashi Iwai {
4708e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4709e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
4710e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
4711e6b85f3cSTakashi Iwai }
4712e6b85f3cSTakashi Iwai 
4713ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
4714ac2e8736STakashi Iwai 				  struct hda_codec *codec,
4715ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
4716ac2e8736STakashi Iwai 				  int action)
4717ac2e8736STakashi Iwai {
4718ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4719ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
4720ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
4721ac2e8736STakashi Iwai }
4722ac2e8736STakashi Iwai 
4723352f7f91STakashi Iwai /*
4724352f7f91STakashi Iwai  * Analog playback callbacks
4725352f7f91STakashi Iwai  */
4726352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
4727352f7f91STakashi Iwai 			     struct hda_codec *codec,
4728352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
4729352f7f91STakashi Iwai {
4730352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
473138cf6f1aSTakashi Iwai 	int err;
473238cf6f1aSTakashi Iwai 
473338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
473438cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
473538cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
4736352f7f91STakashi Iwai 					     hinfo);
4737e6b85f3cSTakashi Iwai 	if (!err) {
473838cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
4739e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4740e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
4741e6b85f3cSTakashi Iwai 	}
474238cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
474338cf6f1aSTakashi Iwai 	return err;
4744352f7f91STakashi Iwai }
4745352f7f91STakashi Iwai 
4746352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
474797ec558aSTakashi Iwai 				struct hda_codec *codec,
474897ec558aSTakashi Iwai 				unsigned int stream_tag,
474997ec558aSTakashi Iwai 				unsigned int format,
475097ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
475197ec558aSTakashi Iwai {
4752352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4753e6b85f3cSTakashi Iwai 	int err;
4754e6b85f3cSTakashi Iwai 
4755e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4756352f7f91STakashi Iwai 					       stream_tag, format, substream);
4757e6b85f3cSTakashi Iwai 	if (!err)
4758e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4759e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4760e6b85f3cSTakashi Iwai 	return err;
4761352f7f91STakashi Iwai }
476297ec558aSTakashi Iwai 
4763352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4764352f7f91STakashi Iwai 				struct hda_codec *codec,
4765352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4766352f7f91STakashi Iwai {
4767352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4768e6b85f3cSTakashi Iwai 	int err;
4769e6b85f3cSTakashi Iwai 
4770e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4771e6b85f3cSTakashi Iwai 	if (!err)
4772e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4773e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4774e6b85f3cSTakashi Iwai 	return err;
4775352f7f91STakashi Iwai }
4776352f7f91STakashi Iwai 
477738cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
477838cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
477938cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
478038cf6f1aSTakashi Iwai {
478138cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
478238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
478338cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4784e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4785e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
478638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
478738cf6f1aSTakashi Iwai 	return 0;
478838cf6f1aSTakashi Iwai }
478938cf6f1aSTakashi Iwai 
4790ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4791ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4792ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4793ac2e8736STakashi Iwai {
4794ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4795ac2e8736STakashi Iwai 	return 0;
4796ac2e8736STakashi Iwai }
4797ac2e8736STakashi Iwai 
4798ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4799ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4800ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4801ac2e8736STakashi Iwai 			       unsigned int format,
4802ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4803ac2e8736STakashi Iwai {
4804ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4805ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4806ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4807ac2e8736STakashi Iwai 	return 0;
4808ac2e8736STakashi Iwai }
4809ac2e8736STakashi Iwai 
4810ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4811ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4812ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4813ac2e8736STakashi Iwai {
4814ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4815ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4816ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4817ac2e8736STakashi Iwai 	return 0;
4818ac2e8736STakashi Iwai }
4819ac2e8736STakashi Iwai 
4820ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4821ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4822ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4823ac2e8736STakashi Iwai {
4824ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4825ac2e8736STakashi Iwai 	return 0;
4826ac2e8736STakashi Iwai }
4827ac2e8736STakashi Iwai 
482838cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
482938cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
483038cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
483138cf6f1aSTakashi Iwai {
483238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
483338cf6f1aSTakashi Iwai 	int err = 0;
483438cf6f1aSTakashi Iwai 
483538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
483638cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
483738cf6f1aSTakashi Iwai 		err = -EBUSY;
483838cf6f1aSTakashi Iwai 	else
483938cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4840e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4841e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
484238cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
484338cf6f1aSTakashi Iwai 	return err;
484438cf6f1aSTakashi Iwai }
484538cf6f1aSTakashi Iwai 
484638cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
484738cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
484838cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
484938cf6f1aSTakashi Iwai {
485038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
485138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
485238cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4853e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4854e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
485538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
485638cf6f1aSTakashi Iwai 	return 0;
485738cf6f1aSTakashi Iwai }
485838cf6f1aSTakashi Iwai 
4859e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4860e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4861e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4862e6b85f3cSTakashi Iwai 				    unsigned int format,
4863e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4864e6b85f3cSTakashi Iwai {
4865e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4866e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4867e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4868e6b85f3cSTakashi Iwai 	return 0;
4869e6b85f3cSTakashi Iwai }
4870e6b85f3cSTakashi Iwai 
4871e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4872e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4873e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4874e6b85f3cSTakashi Iwai {
4875e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4876e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4877e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4878e6b85f3cSTakashi Iwai 	return 0;
4879e6b85f3cSTakashi Iwai }
4880e6b85f3cSTakashi Iwai 
4881352f7f91STakashi Iwai /*
4882352f7f91STakashi Iwai  * Digital out
4883352f7f91STakashi Iwai  */
4884352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4885352f7f91STakashi Iwai 				 struct hda_codec *codec,
4886352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4887352f7f91STakashi Iwai {
4888352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4889352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4890352f7f91STakashi Iwai }
4891352f7f91STakashi Iwai 
4892352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4893352f7f91STakashi Iwai 				    struct hda_codec *codec,
4894352f7f91STakashi Iwai 				    unsigned int stream_tag,
4895352f7f91STakashi Iwai 				    unsigned int format,
4896352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4897352f7f91STakashi Iwai {
4898352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4899352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4900352f7f91STakashi Iwai 					     stream_tag, format, substream);
4901352f7f91STakashi Iwai }
4902352f7f91STakashi Iwai 
4903352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4904352f7f91STakashi Iwai 				    struct hda_codec *codec,
4905352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4906352f7f91STakashi Iwai {
4907352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4908352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4909352f7f91STakashi Iwai }
4910352f7f91STakashi Iwai 
4911352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4912352f7f91STakashi Iwai 				  struct hda_codec *codec,
4913352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4914352f7f91STakashi Iwai {
4915352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4916352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4917352f7f91STakashi Iwai }
4918352f7f91STakashi Iwai 
4919352f7f91STakashi Iwai /*
4920352f7f91STakashi Iwai  * Analog capture
4921352f7f91STakashi Iwai  */
4922ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4923ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4924ac2e8736STakashi Iwai 
4925352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4926352f7f91STakashi Iwai 				   struct hda_codec *codec,
4927352f7f91STakashi Iwai 				   unsigned int stream_tag,
4928352f7f91STakashi Iwai 				   unsigned int format,
4929352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4930352f7f91STakashi Iwai {
4931352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4932352f7f91STakashi Iwai 
4933352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
493497ec558aSTakashi Iwai 				   stream_tag, 0, format);
4935ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4936ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
493797ec558aSTakashi Iwai 	return 0;
493897ec558aSTakashi Iwai }
493997ec558aSTakashi Iwai 
4940352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
494197ec558aSTakashi Iwai 				   struct hda_codec *codec,
494297ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
494397ec558aSTakashi Iwai {
4944352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
494597ec558aSTakashi Iwai 
4946352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4947352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4948ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4949ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
495097ec558aSTakashi Iwai 	return 0;
495197ec558aSTakashi Iwai }
495297ec558aSTakashi Iwai 
4953352f7f91STakashi Iwai /*
4954352f7f91STakashi Iwai  */
4955352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4956352f7f91STakashi Iwai 	.substreams = 1,
4957352f7f91STakashi Iwai 	.channels_min = 2,
4958352f7f91STakashi Iwai 	.channels_max = 8,
4959352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4960352f7f91STakashi Iwai 	.ops = {
4961352f7f91STakashi Iwai 		.open = playback_pcm_open,
496238cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4963352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4964352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4965352f7f91STakashi Iwai 	},
4966352f7f91STakashi Iwai };
4967352f7f91STakashi Iwai 
4968352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4969352f7f91STakashi Iwai 	.substreams = 1,
4970352f7f91STakashi Iwai 	.channels_min = 2,
4971352f7f91STakashi Iwai 	.channels_max = 2,
4972352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4973ac2e8736STakashi Iwai 	.ops = {
4974ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4975ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4976ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4977ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4978ac2e8736STakashi Iwai 	},
4979352f7f91STakashi Iwai };
4980352f7f91STakashi Iwai 
4981352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4982352f7f91STakashi Iwai 	.substreams = 1,
4983352f7f91STakashi Iwai 	.channels_min = 2,
4984352f7f91STakashi Iwai 	.channels_max = 2,
4985352f7f91STakashi Iwai 	/* NID is set in build_pcms */
498638cf6f1aSTakashi Iwai 	.ops = {
498738cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4988e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4989e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4990e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
499138cf6f1aSTakashi Iwai 	},
4992352f7f91STakashi Iwai };
4993352f7f91STakashi Iwai 
4994352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4995352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4996352f7f91STakashi Iwai 	.channels_min = 2,
4997352f7f91STakashi Iwai 	.channels_max = 2,
4998352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4999352f7f91STakashi Iwai 	.ops = {
5000ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5001ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5002352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5003352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5004352f7f91STakashi Iwai 	},
5005352f7f91STakashi Iwai };
5006352f7f91STakashi Iwai 
5007352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5008352f7f91STakashi Iwai 	.substreams = 1,
5009352f7f91STakashi Iwai 	.channels_min = 2,
5010352f7f91STakashi Iwai 	.channels_max = 2,
5011352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5012352f7f91STakashi Iwai 	.ops = {
5013352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5014352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5015352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5016352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5017352f7f91STakashi Iwai 	},
5018352f7f91STakashi Iwai };
5019352f7f91STakashi Iwai 
5020352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5021352f7f91STakashi Iwai 	.substreams = 1,
5022352f7f91STakashi Iwai 	.channels_min = 2,
5023352f7f91STakashi Iwai 	.channels_max = 2,
5024352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5025352f7f91STakashi Iwai };
5026352f7f91STakashi Iwai 
5027352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5028352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5029352f7f91STakashi Iwai 	.substreams = 0,
5030352f7f91STakashi Iwai 	.channels_min = 0,
5031352f7f91STakashi Iwai 	.channels_max = 0,
5032352f7f91STakashi Iwai };
5033352f7f91STakashi Iwai 
5034352f7f91STakashi Iwai /*
5035352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5036352f7f91STakashi Iwai  */
5037352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
50381da177e4SLinus Torvalds {
5039352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5040352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
50411da177e4SLinus Torvalds 
5042352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5043352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5044352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5045352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5046352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5047352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5048352f7f91STakashi Iwai 					   spec->cur_adc_format);
5049352f7f91STakashi Iwai 		return true;
5050352f7f91STakashi Iwai 	}
5051352f7f91STakashi Iwai 	return false;
5052352f7f91STakashi Iwai }
5053352f7f91STakashi Iwai 
5054352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5055352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5056352f7f91STakashi Iwai 				       struct hda_codec *codec,
5057352f7f91STakashi Iwai 				       unsigned int stream_tag,
5058352f7f91STakashi Iwai 				       unsigned int format,
5059352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5060352f7f91STakashi Iwai {
5061352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5062352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5063352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5064352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5065352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
50661da177e4SLinus Torvalds 	return 0;
50671da177e4SLinus Torvalds }
50681da177e4SLinus Torvalds 
5069352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5070352f7f91STakashi Iwai 				       struct hda_codec *codec,
5071352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5072352f7f91STakashi Iwai {
5073352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5074352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5075352f7f91STakashi Iwai 	spec->cur_adc = 0;
5076352f7f91STakashi Iwai 	return 0;
5077352f7f91STakashi Iwai }
5078352f7f91STakashi Iwai 
5079352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5080352f7f91STakashi Iwai 	.substreams = 1,
5081352f7f91STakashi Iwai 	.channels_min = 2,
5082352f7f91STakashi Iwai 	.channels_max = 2,
5083352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5084352f7f91STakashi Iwai 	.ops = {
5085352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5086352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5087352f7f91STakashi Iwai 	},
5088352f7f91STakashi Iwai };
5089352f7f91STakashi Iwai 
5090f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5091f873e536STakashi Iwai 				 const char *chip_name)
5092f873e536STakashi Iwai {
5093f873e536STakashi Iwai 	char *p;
5094f873e536STakashi Iwai 
5095f873e536STakashi Iwai 	if (*str)
5096f873e536STakashi Iwai 		return;
5097f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
5098f873e536STakashi Iwai 
5099f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5100f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5101f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5102f873e536STakashi Iwai 			*p = 0;
5103f873e536STakashi Iwai 			break;
5104f873e536STakashi Iwai 		}
5105f873e536STakashi Iwai 	}
5106f873e536STakashi Iwai 	strlcat(str, sfx, len);
5107f873e536STakashi Iwai }
5108f873e536STakashi Iwai 
5109dda42bd0STakashi Iwai /**
5110dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5111dda42bd0STakashi Iwai  * @codec: the HDA codec
5112dda42bd0STakashi Iwai  *
5113dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5114dda42bd0STakashi Iwai  */
5115352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5116352f7f91STakashi Iwai {
5117352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5118bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5119352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
5120352f7f91STakashi Iwai 	bool have_multi_adcs;
5121352f7f91STakashi Iwai 
5122352f7f91STakashi Iwai 	if (spec->no_analog)
5123352f7f91STakashi Iwai 		goto skip_analog;
5124352f7f91STakashi Iwai 
5125f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5126f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
5127f873e536STakashi Iwai 			     " Analog", codec->chip_name);
5128bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5129bbbc7e85STakashi Iwai 	if (!info)
5130bbbc7e85STakashi Iwai 		return -ENOMEM;
5131bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5132352f7f91STakashi Iwai 
5133352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5134352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
5135352f7f91STakashi Iwai 		if (!p)
5136352f7f91STakashi Iwai 			p = &pcm_analog_playback;
5137352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5138352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
5139352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5140352f7f91STakashi Iwai 			spec->multiout.max_channels;
5141352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5142352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5143352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5144352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5145352f7f91STakashi Iwai 	}
5146352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5147352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
5148352f7f91STakashi Iwai 		if (!p) {
5149352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
5150352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
5151352f7f91STakashi Iwai 			else
5152352f7f91STakashi Iwai 				p = &pcm_analog_capture;
5153352f7f91STakashi Iwai 		}
5154352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5155352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
5156352f7f91STakashi Iwai 	}
5157352f7f91STakashi Iwai 
5158352f7f91STakashi Iwai  skip_analog:
5159352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5160352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5161f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5162352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
5163f873e536STakashi Iwai 				     " Digital", codec->chip_name);
5164bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5165bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5166bbbc7e85STakashi Iwai 		if (!info)
5167bbbc7e85STakashi Iwai 			return -ENOMEM;
5168352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5169bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5170352f7f91STakashi Iwai 		if (spec->dig_out_type)
5171352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5172352f7f91STakashi Iwai 		else
5173352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5174352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
5175352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
5176352f7f91STakashi Iwai 			if (!p)
5177352f7f91STakashi Iwai 				p = &pcm_digital_playback;
5178352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5179352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
5180352f7f91STakashi Iwai 		}
5181352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
5182352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
5183352f7f91STakashi Iwai 			if (!p)
5184352f7f91STakashi Iwai 				p = &pcm_digital_capture;
5185352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5186352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
5187352f7f91STakashi Iwai 		}
5188352f7f91STakashi Iwai 	}
5189352f7f91STakashi Iwai 
5190352f7f91STakashi Iwai 	if (spec->no_analog)
5191352f7f91STakashi Iwai 		return 0;
5192352f7f91STakashi Iwai 
5193352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5194352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5195352f7f91STakashi Iwai 	 */
5196352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5197352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5198352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5199352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5200a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5201a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
5202a607148fSTakashi Iwai 			     " Alt Analog", codec->chip_name);
5203bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5204bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5205bbbc7e85STakashi Iwai 		if (!info)
5206bbbc7e85STakashi Iwai 			return -ENOMEM;
5207bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5208352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
5209352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
5210352f7f91STakashi Iwai 			if (!p)
5211352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
5212352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5213352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
5214352f7f91STakashi Iwai 				spec->alt_dac_nid;
5215352f7f91STakashi Iwai 		} else {
5216352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
5217352f7f91STakashi Iwai 				pcm_null_stream;
5218352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
5219352f7f91STakashi Iwai 		}
5220352f7f91STakashi Iwai 		if (have_multi_adcs) {
5221352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
5222352f7f91STakashi Iwai 			if (!p)
5223352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
5224352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5225352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
5226352f7f91STakashi Iwai 				spec->adc_nids[1];
5227352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5228352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5229352f7f91STakashi Iwai 		} else {
5230352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
5231352f7f91STakashi Iwai 				pcm_null_stream;
5232352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
5233352f7f91STakashi Iwai 		}
52341da177e4SLinus Torvalds 	}
52351da177e4SLinus Torvalds 
52361da177e4SLinus Torvalds 	return 0;
52371da177e4SLinus Torvalds }
52382698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5239352f7f91STakashi Iwai 
5240352f7f91STakashi Iwai 
5241352f7f91STakashi Iwai /*
5242352f7f91STakashi Iwai  * Standard auto-parser initializations
5243352f7f91STakashi Iwai  */
5244352f7f91STakashi Iwai 
5245d4156930STakashi Iwai /* configure the given path as a proper output */
52462c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5247352f7f91STakashi Iwai {
5248352f7f91STakashi Iwai 	struct nid_path *path;
5249d4156930STakashi Iwai 	hda_nid_t pin;
5250352f7f91STakashi Iwai 
5251196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5252d4156930STakashi Iwai 	if (!path || !path->depth)
5253352f7f91STakashi Iwai 		return;
5254d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
52552c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
525665033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
525765033cc8STakashi Iwai 			      aamix_default(codec->spec));
5258e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5259352f7f91STakashi Iwai }
5260352f7f91STakashi Iwai 
5261352f7f91STakashi Iwai /* initialize primary output paths */
5262352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5263352f7f91STakashi Iwai {
5264352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5265352f7f91STakashi Iwai 	int i;
5266352f7f91STakashi Iwai 
5267d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
52682c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5269352f7f91STakashi Iwai }
5270352f7f91STakashi Iwai 
5271db23fd19STakashi Iwai 
52722c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5273352f7f91STakashi Iwai {
5274352f7f91STakashi Iwai 	int i;
5275352f7f91STakashi Iwai 
5276d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
52772c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5278352f7f91STakashi Iwai }
5279db23fd19STakashi Iwai 
5280db23fd19STakashi Iwai /* initialize hp and speaker paths */
5281db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5282db23fd19STakashi Iwai {
5283db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5284db23fd19STakashi Iwai 
5285db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
52862c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5287db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5288db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
52892c12c30dSTakashi Iwai 				 spec->speaker_paths);
5290352f7f91STakashi Iwai }
5291352f7f91STakashi Iwai 
5292352f7f91STakashi Iwai /* initialize multi-io paths */
5293352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5294352f7f91STakashi Iwai {
5295352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5296352f7f91STakashi Iwai 	int i;
5297352f7f91STakashi Iwai 
5298352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5299352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5300352f7f91STakashi Iwai 		struct nid_path *path;
5301196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5302352f7f91STakashi Iwai 		if (!path)
5303352f7f91STakashi Iwai 			continue;
5304352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5305352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
53062c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
530765033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
530865033cc8STakashi Iwai 				      aamix_default(spec));
5309352f7f91STakashi Iwai 	}
5310352f7f91STakashi Iwai }
5311352f7f91STakashi Iwai 
53124f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
53134f7f67fbSTakashi Iwai {
53144f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
53154f7f67fbSTakashi Iwai 
53164f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
53174f7f67fbSTakashi Iwai 		return;
53184f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
53194f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
53204f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
53214f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
53224f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
53234f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
53244f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
53254f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
53264f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
53274f7f67fbSTakashi Iwai }
53284f7f67fbSTakashi Iwai 
5329352f7f91STakashi Iwai /* set up input pins and loopback paths */
5330352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5331352f7f91STakashi Iwai {
5332352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5333352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5334352f7f91STakashi Iwai 	int i;
5335352f7f91STakashi Iwai 
5336352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5337352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5338352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
53392c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5340352f7f91STakashi Iwai 
5341352f7f91STakashi Iwai 		/* init loopback inputs */
5342352f7f91STakashi Iwai 		if (spec->mixer_nid) {
53433e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
53443e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5345352f7f91STakashi Iwai 		}
5346352f7f91STakashi Iwai 	}
5347352f7f91STakashi Iwai }
5348352f7f91STakashi Iwai 
5349352f7f91STakashi Iwai /* initialize ADC paths */
5350352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5351352f7f91STakashi Iwai {
5352352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5353352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5354352f7f91STakashi Iwai 	struct nid_path *path;
5355352f7f91STakashi Iwai 	int i, c, nums;
5356352f7f91STakashi Iwai 
5357352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5358352f7f91STakashi Iwai 		nums = 1;
5359352f7f91STakashi Iwai 	else
5360352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5361352f7f91STakashi Iwai 
5362352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5363352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5364c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5365352f7f91STakashi Iwai 			if (path) {
5366352f7f91STakashi Iwai 				bool active = path->active;
5367352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5368352f7f91STakashi Iwai 					active = true;
5369352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5370352f7f91STakashi Iwai 			}
5371352f7f91STakashi Iwai 		}
5372967303daSTakashi Iwai 		if (spec->hp_mic)
5373967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5374352f7f91STakashi Iwai 	}
5375352f7f91STakashi Iwai 
5376352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
53777fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
5378352f7f91STakashi Iwai }
5379352f7f91STakashi Iwai 
5380352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5381352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5382352f7f91STakashi Iwai {
5383352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5384352f7f91STakashi Iwai 	int i;
5385352f7f91STakashi Iwai 	hda_nid_t pin;
5386352f7f91STakashi Iwai 
5387d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
53882c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5389352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
53902430d7b7STakashi Iwai 	if (pin) {
53912c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
53923e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
53932430d7b7STakashi Iwai 	}
5394352f7f91STakashi Iwai }
5395352f7f91STakashi Iwai 
5396973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5397973e4972STakashi Iwai  * invalid unsol tags by some reason
5398973e4972STakashi Iwai  */
5399973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5400973e4972STakashi Iwai {
5401973e4972STakashi Iwai 	int i;
5402973e4972STakashi Iwai 
5403973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5404973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5405973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5406973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5407973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5408973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5409973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5410973e4972STakashi Iwai 	}
5411973e4972STakashi Iwai }
5412973e4972STakashi Iwai 
5413dda42bd0STakashi Iwai /**
5414dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
5415dda42bd0STakashi Iwai  * @codec: the HDA codec
5416dda42bd0STakashi Iwai  *
5417dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
54185187ac16STakashi Iwai  */
5419352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5420352f7f91STakashi Iwai {
5421352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5422352f7f91STakashi Iwai 
5423352f7f91STakashi Iwai 	if (spec->init_hook)
5424352f7f91STakashi Iwai 		spec->init_hook(codec);
5425352f7f91STakashi Iwai 
5426352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5427352f7f91STakashi Iwai 
54283bbcd274STakashi Iwai 	codec->cached_write = 1;
54293bbcd274STakashi Iwai 
5430352f7f91STakashi Iwai 	init_multi_out(codec);
5431352f7f91STakashi Iwai 	init_extra_out(codec);
5432352f7f91STakashi Iwai 	init_multi_io(codec);
54334f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5434352f7f91STakashi Iwai 	init_analog_input(codec);
5435352f7f91STakashi Iwai 	init_input_src(codec);
5436352f7f91STakashi Iwai 	init_digital(codec);
5437352f7f91STakashi Iwai 
5438973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5439973e4972STakashi Iwai 
5440352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5441a5cc2509STakashi Iwai 	update_automute_all(codec);
5442352f7f91STakashi Iwai 
5443dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec);
54443bbcd274STakashi Iwai 
5445352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5446352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5447352f7f91STakashi Iwai 
5448352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5449352f7f91STakashi Iwai 	return 0;
5450352f7f91STakashi Iwai }
54512698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5452fce52a3bSTakashi Iwai 
5453dda42bd0STakashi Iwai /**
5454dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
5455dda42bd0STakashi Iwai  * @codec: the HDA codec
5456dda42bd0STakashi Iwai  *
5457dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
54585187ac16STakashi Iwai  */
5459fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5460fce52a3bSTakashi Iwai {
54618a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
5462fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5463fce52a3bSTakashi Iwai 	kfree(codec->spec);
5464fce52a3bSTakashi Iwai 	codec->spec = NULL;
5465fce52a3bSTakashi Iwai }
54662698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
5467fce52a3bSTakashi Iwai 
5468fce52a3bSTakashi Iwai #ifdef CONFIG_PM
5469dda42bd0STakashi Iwai /**
5470dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
5471dda42bd0STakashi Iwai  * @codec: the HDA codec
5472dda42bd0STakashi Iwai  * @nid: NID to inspect
5473dda42bd0STakashi Iwai  *
5474dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
54755187ac16STakashi Iwai  */
5476fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5477fce52a3bSTakashi Iwai {
5478fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5479fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5480fce52a3bSTakashi Iwai }
54812698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
5482fce52a3bSTakashi Iwai #endif
5483352f7f91STakashi Iwai 
5484352f7f91STakashi Iwai 
5485352f7f91STakashi Iwai /*
5486352f7f91STakashi Iwai  * the generic codec support
5487352f7f91STakashi Iwai  */
54881da177e4SLinus Torvalds 
5489352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5490352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5491352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5492352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5493fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5494352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
549583012a7cSTakashi Iwai #ifdef CONFIG_PM
5496fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5497cb53c626STakashi Iwai #endif
54981da177e4SLinus Torvalds };
54991da177e4SLinus Torvalds 
5500d8a766a1STakashi Iwai /*
5501dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
5502dda42bd0STakashi Iwai  * @codec: the HDA codec
5503dda42bd0STakashi Iwai  */
5504d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
55051da177e4SLinus Torvalds {
5506352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
55071da177e4SLinus Torvalds 	int err;
55081da177e4SLinus Torvalds 
5509e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5510352f7f91STakashi Iwai 	if (!spec)
55111da177e4SLinus Torvalds 		return -ENOMEM;
5512352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
55131da177e4SLinus Torvalds 	codec->spec = spec;
55141da177e4SLinus Torvalds 
55159eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
55169eb413e5STakashi Iwai 	if (err < 0)
55179eb413e5STakashi Iwai 		return err;
55189eb413e5STakashi Iwai 
55199eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5520352f7f91STakashi Iwai 	if (err < 0)
55211da177e4SLinus Torvalds 		goto error;
55221da177e4SLinus Torvalds 
55231da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
55241da177e4SLinus Torvalds 	return 0;
55251da177e4SLinus Torvalds 
55261da177e4SLinus Torvalds error:
5527fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
55281da177e4SLinus Torvalds 	return err;
55291da177e4SLinus Torvalds }
5530d8a766a1STakashi Iwai 
5531d8a766a1STakashi Iwai static const struct hda_codec_preset snd_hda_preset_generic[] = {
5532d8a766a1STakashi Iwai 	{ .id = HDA_CODEC_ID_GENERIC, .patch = snd_hda_parse_generic_codec },
5533d8a766a1STakashi Iwai 	{} /* terminator */
5534d8a766a1STakashi Iwai };
5535d8a766a1STakashi Iwai 
5536d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
5537d8a766a1STakashi Iwai 	.preset = snd_hda_preset_generic,
5538d8a766a1STakashi Iwai };
5539d8a766a1STakashi Iwai 
5540d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
5541b21bdd0dSTakashi Iwai 
5542b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
5543b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
5544