xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision a8f20fd2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Generic widget tree parser
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  This driver is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
101da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
111da177e4SLinus Torvalds  *  (at your option) any later version.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *  This driver is distributed in the hope that it will be useful,
141da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
151da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4SLinus Torvalds  *  GNU General Public License for more details.
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  *  You should have received a copy of the GNU General Public License
191da177e4SLinus Torvalds  *  along with this program; if not, write to the Free Software
201da177e4SLinus Torvalds  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
211da177e4SLinus Torvalds  */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/slab.h>
25d81a6d71SPaul Gortmaker #include <linux/export.h>
26352f7f91STakashi Iwai #include <linux/sort.h>
2755196fffSTakashi Iwai #include <linux/delay.h>
28f873e536STakashi Iwai #include <linux/ctype.h>
29f873e536STakashi Iwai #include <linux/string.h>
3029476558STakashi Iwai #include <linux/bitops.h>
31b21bdd0dSTakashi Iwai #include <linux/module.h>
321da177e4SLinus Torvalds #include <sound/core.h>
33352f7f91STakashi Iwai #include <sound/jack.h>
34d89c6c0cSTakashi Iwai #include <sound/tlv.h>
351da177e4SLinus Torvalds #include "hda_codec.h"
361da177e4SLinus Torvalds #include "hda_local.h"
37352f7f91STakashi Iwai #include "hda_auto_parser.h"
38352f7f91STakashi Iwai #include "hda_jack.h"
397504b6cdSTakashi Iwai #include "hda_beep.h"
40352f7f91STakashi Iwai #include "hda_generic.h"
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds 
43dda42bd0STakashi Iwai /**
44dda42bd0STakashi Iwai  * snd_hda_gen_spec_init - initialize hda_gen_spec struct
45dda42bd0STakashi Iwai  * @spec: hda_gen_spec object to initialize
46dda42bd0STakashi Iwai  *
47dda42bd0STakashi Iwai  * Initialize the given hda_gen_spec object.
48dda42bd0STakashi Iwai  */
49352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
501da177e4SLinus Torvalds {
51352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
52352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
530186f4f4STakashi Iwai 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
5438cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
55352f7f91STakashi Iwai 	return 0;
56352f7f91STakashi Iwai }
572698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
581da177e4SLinus Torvalds 
59dda42bd0STakashi Iwai /**
60dda42bd0STakashi Iwai  * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
61dda42bd0STakashi Iwai  * @spec: hda_gen_spec object
62dda42bd0STakashi Iwai  * @name: name string to override the template, NULL if unchanged
63dda42bd0STakashi Iwai  * @temp: template for the new kctl
64dda42bd0STakashi Iwai  *
65dda42bd0STakashi Iwai  * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
66dda42bd0STakashi Iwai  * element based on the given snd_kcontrol_new template @temp and the
67dda42bd0STakashi Iwai  * name string @name to the list in @spec.
68dda42bd0STakashi Iwai  * Returns the newly created object or NULL as error.
69dda42bd0STakashi Iwai  */
7012c93df6STakashi Iwai struct snd_kcontrol_new *
7112c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
72352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
73352f7f91STakashi Iwai {
74352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
75352f7f91STakashi Iwai 	if (!knew)
76352f7f91STakashi Iwai 		return NULL;
77352f7f91STakashi Iwai 	*knew = *temp;
78352f7f91STakashi Iwai 	if (name)
79352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
80352f7f91STakashi Iwai 	else if (knew->name)
81352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
82352f7f91STakashi Iwai 	if (!knew->name)
83352f7f91STakashi Iwai 		return NULL;
84352f7f91STakashi Iwai 	return knew;
85352f7f91STakashi Iwai }
862698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
87352f7f91STakashi Iwai 
88352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
89352f7f91STakashi Iwai {
90352f7f91STakashi Iwai 	if (spec->kctls.list) {
91352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
92352f7f91STakashi Iwai 		int i;
93352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
94352f7f91STakashi Iwai 			kfree(kctl[i].name);
95352f7f91STakashi Iwai 	}
96352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
97352f7f91STakashi Iwai }
98352f7f91STakashi Iwai 
99a8dca460STakashi Iwai static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
100352f7f91STakashi Iwai {
1011da177e4SLinus Torvalds 	if (!spec)
1021da177e4SLinus Torvalds 		return;
103352f7f91STakashi Iwai 	free_kctls(spec);
104352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1050186f4f4STakashi Iwai 	snd_array_free(&spec->loopback_list);
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds /*
1091c70a583STakashi Iwai  * store user hints
1101c70a583STakashi Iwai  */
1111c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
1121c70a583STakashi Iwai {
1131c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1141c70a583STakashi Iwai 	int val;
1151c70a583STakashi Iwai 
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1221c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1231c70a583STakashi Iwai 	if (val >= 0)
1241c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1251c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1261c70a583STakashi Iwai 	if (val >= 0)
1271c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1281c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1291c70a583STakashi Iwai 	if (val >= 0)
1301c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1311c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1321c70a583STakashi Iwai 	if (val >= 0)
1331c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1341c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1351c70a583STakashi Iwai 	if (val >= 0)
1361c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1371c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1381c70a583STakashi Iwai 	if (val >= 0)
1391c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1401c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1411c70a583STakashi Iwai 	if (val >= 0)
1421c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
143967b1307STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_save_node");
144e6feb5d0STakashi Iwai 	if (val >= 0)
145967b1307STakashi Iwai 		codec->power_save_node = !!val;
1461c70a583STakashi Iwai 
147f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
148f72706beSTakashi Iwai 	if (val >= 0)
149f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1531c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1541c70a583STakashi Iwai 	if (val >= 0)
1551c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1567eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1577eebffd3STakashi Iwai 	if (val >= 0)
1587eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1591c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1601c70a583STakashi Iwai 	if (val >= 0)
1611c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1621c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1631c70a583STakashi Iwai 	if (val >= 0)
1641c70a583STakashi Iwai 		spec->no_primary_hp = !val;
165da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
166da96fb5bSTakashi Iwai 	if (val >= 0)
167da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1681c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1691c70a583STakashi Iwai 	if (val >= 0)
1701c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1711c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1721c70a583STakashi Iwai 	if (val >= 0)
1731c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1741c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1751c70a583STakashi Iwai 	if (val >= 0)
1761c70a583STakashi Iwai 		spec->indep_hp = !!val;
1771c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1781c70a583STakashi Iwai 	if (val >= 0)
1791c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
180f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1811c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1821c70a583STakashi Iwai 	if (val >= 0)
183f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
18429476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
18529476558STakashi Iwai 	if (val >= 0)
186f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
187f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
188f811c3cfSTakashi Iwai 	if (val >= 0)
189f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
19055196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
19155196fffSTakashi Iwai 	if (val >= 0)
19255196fffSTakashi Iwai 		spec->power_down_unused = !!val;
193967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
194967303daSTakashi Iwai 	if (val >= 0)
195967303daSTakashi Iwai 		spec->hp_mic = !!val;
196967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
197967303daSTakashi Iwai 	if (val >= 0)
198967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1997480316cSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "vmaster");
2007480316cSTakashi Iwai 	if (val >= 0)
2017480316cSTakashi Iwai 		spec->suppress_vmaster = !val;
2021c70a583STakashi Iwai 
2031c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
2041c70a583STakashi Iwai 		spec->mixer_nid = val;
2051c70a583STakashi Iwai }
2061c70a583STakashi Iwai 
2071c70a583STakashi Iwai /*
2082c12c30dSTakashi Iwai  * pin control value accesses
2092c12c30dSTakashi Iwai  */
2102c12c30dSTakashi Iwai 
2112c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
2122c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
2132c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
2142c12c30dSTakashi Iwai 
2152c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
2162c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
2172c12c30dSTakashi Iwai {
2182c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
2192c12c30dSTakashi Iwai }
2202c12c30dSTakashi Iwai 
2212c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2222c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2232c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2242c12c30dSTakashi Iwai {
2252c12c30dSTakashi Iwai 	if (!pin)
2262c12c30dSTakashi Iwai 		return;
2272c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2282c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2292c12c30dSTakashi Iwai 	if (do_write)
2302c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2312c12c30dSTakashi Iwai }
2322c12c30dSTakashi Iwai 
2332c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2342c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2352c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2362c12c30dSTakashi Iwai {
2372c12c30dSTakashi Iwai 	int i;
2382c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2392c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2402c12c30dSTakashi Iwai }
2412c12c30dSTakashi Iwai 
2422c12c30dSTakashi Iwai /*
243352f7f91STakashi Iwai  * parsing paths
2441da177e4SLinus Torvalds  */
2451da177e4SLinus Torvalds 
2463ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2473ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2483ca529d3STakashi Iwai {
2493ca529d3STakashi Iwai 	int i;
2503ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2513ca529d3STakashi Iwai 		if (list[i] == nid)
2523ca529d3STakashi Iwai 			return i;
2533ca529d3STakashi Iwai 	return -1;
2543ca529d3STakashi Iwai }
2553ca529d3STakashi Iwai 
2563ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2573ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2583ca529d3STakashi Iwai {
2593ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2603ca529d3STakashi Iwai }
2613ca529d3STakashi Iwai 
262f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
263f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2643ca529d3STakashi Iwai 				     int anchor_nid)
2651da177e4SLinus Torvalds {
266352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
267352f7f91STakashi Iwai 	int i;
2681da177e4SLinus Torvalds 
269352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
270352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
271352f7f91STakashi Iwai 		if (path->depth <= 0)
272352f7f91STakashi Iwai 			continue;
273352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
274f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2753ca529d3STakashi Iwai 			if (!anchor_nid ||
2763ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2773ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
278352f7f91STakashi Iwai 				return path;
2791da177e4SLinus Torvalds 		}
280f5172a7eSTakashi Iwai 	}
2811da177e4SLinus Torvalds 	return NULL;
2821da177e4SLinus Torvalds }
283f5172a7eSTakashi Iwai 
284dda42bd0STakashi Iwai /**
285dda42bd0STakashi Iwai  * snd_hda_get_path_idx - get the index number corresponding to the path
286dda42bd0STakashi Iwai  * instance
287dda42bd0STakashi Iwai  * @codec: the HDA codec
288dda42bd0STakashi Iwai  * @path: nid_path object
289dda42bd0STakashi Iwai  *
290dda42bd0STakashi Iwai  * The returned index starts from 1, i.e. the actual array index with offset 1,
291dda42bd0STakashi Iwai  * and zero is handled as an invalid path
292196c1766STakashi Iwai  */
293196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
294196c1766STakashi Iwai {
295196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
296196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
297196c1766STakashi Iwai 	ssize_t idx;
298196c1766STakashi Iwai 
299196c1766STakashi Iwai 	if (!spec->paths.used)
300196c1766STakashi Iwai 		return 0;
301196c1766STakashi Iwai 	idx = path - array;
302196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
303196c1766STakashi Iwai 		return 0;
304196c1766STakashi Iwai 	return idx + 1;
305196c1766STakashi Iwai }
3062698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
307196c1766STakashi Iwai 
308dda42bd0STakashi Iwai /**
309dda42bd0STakashi Iwai  * snd_hda_get_path_from_idx - get the path instance corresponding to the
310dda42bd0STakashi Iwai  * given index number
311dda42bd0STakashi Iwai  * @codec: the HDA codec
312dda42bd0STakashi Iwai  * @idx: the path index
313dda42bd0STakashi Iwai  */
314196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
315196c1766STakashi Iwai {
316196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
317196c1766STakashi Iwai 
318196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
319196c1766STakashi Iwai 		return NULL;
320196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
321196c1766STakashi Iwai }
3222698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
323196c1766STakashi Iwai 
324352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
325352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3261da177e4SLinus Torvalds {
327352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
328352f7f91STakashi Iwai 	int i;
329352f7f91STakashi Iwai 
330352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
331352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
332352f7f91STakashi Iwai 		if (path->path[0] == nid)
333352f7f91STakashi Iwai 			return true;
334352f7f91STakashi Iwai 	}
335352f7f91STakashi Iwai 	return false;
3361da177e4SLinus Torvalds }
3371da177e4SLinus Torvalds 
338352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
339352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
340352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3411da177e4SLinus Torvalds {
342352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
343352f7f91STakashi Iwai 		return false;
344352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3451da177e4SLinus Torvalds }
3461da177e4SLinus Torvalds 
347352f7f91STakashi Iwai /* nid, dir and idx */
348352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
349352f7f91STakashi Iwai 
350352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
351352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3521da177e4SLinus Torvalds {
353352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
354352f7f91STakashi Iwai 	int i;
355352f7f91STakashi Iwai 
356352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
357352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
358352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
359352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
360352f7f91STakashi Iwai 			return true;
361352f7f91STakashi Iwai 	}
362352f7f91STakashi Iwai 	return false;
3631da177e4SLinus Torvalds }
3641da177e4SLinus Torvalds 
365352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
366352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3678999bf0aSTakashi Iwai 			      int dir, int idx, int type)
368cb53c626STakashi Iwai {
369352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3708999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
371cb53c626STakashi Iwai }
372352f7f91STakashi Iwai 
3734e76a883STakashi Iwai static void print_nid_path(struct hda_codec *codec,
3744e76a883STakashi Iwai 			   const char *pfx, struct nid_path *path)
3750c8c0f56STakashi Iwai {
3760c8c0f56STakashi Iwai 	char buf[40];
377d82353e5SJoe Perches 	char *pos = buf;
3780c8c0f56STakashi Iwai 	int i;
3790c8c0f56STakashi Iwai 
380d82353e5SJoe Perches 	*pos = 0;
381d82353e5SJoe Perches 	for (i = 0; i < path->depth; i++)
382d82353e5SJoe Perches 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
383d82353e5SJoe Perches 				 pos != buf ? ":" : "",
384d82353e5SJoe Perches 				 path->path[i]);
3850c8c0f56STakashi Iwai 
386d82353e5SJoe Perches 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
3870c8c0f56STakashi Iwai }
3880c8c0f56STakashi Iwai 
389352f7f91STakashi Iwai /* called recursively */
390352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
391352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3923ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3933ca529d3STakashi Iwai 			     int depth)
394352f7f91STakashi Iwai {
395ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
396352f7f91STakashi Iwai 	int i, nums;
397352f7f91STakashi Iwai 
3983ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3993ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
4003ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
4013ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
402352f7f91STakashi Iwai 
403ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
404352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
405352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
406352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
407352f7f91STakashi Iwai 			 * try to find an empty DAC
408352f7f91STakashi Iwai 			 */
409352f7f91STakashi Iwai 			if (from_nid ||
410352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
411352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
412352f7f91STakashi Iwai 				continue;
413352f7f91STakashi Iwai 		}
4143ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
4153ca529d3STakashi Iwai 		if (anchor_nid <= 0)
416352f7f91STakashi Iwai 			goto found;
417352f7f91STakashi Iwai 	}
418352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
419352f7f91STakashi Iwai 		return false;
420352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
421352f7f91STakashi Iwai 		unsigned int type;
422352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
423352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
424352f7f91STakashi Iwai 		    type == AC_WID_PIN)
425352f7f91STakashi Iwai 			continue;
426352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4273ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
428352f7f91STakashi Iwai 			goto found;
429352f7f91STakashi Iwai 	}
430352f7f91STakashi Iwai 	return false;
431352f7f91STakashi Iwai 
432352f7f91STakashi Iwai  found:
433352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
434352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
435352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
436352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
437352f7f91STakashi Iwai 	path->depth++;
438352f7f91STakashi Iwai 	return true;
439352f7f91STakashi Iwai }
440352f7f91STakashi Iwai 
441c4a58c30STakashi Iwai /*
442dda42bd0STakashi Iwai  * snd_hda_parse_nid_path - parse the widget path from the given nid to
443dda42bd0STakashi Iwai  * the target nid
444dda42bd0STakashi Iwai  * @codec: the HDA codec
445dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
446dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
447dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication
448dda42bd0STakashi Iwai  * @path: the path object to store the result
449dda42bd0STakashi Iwai  *
450dda42bd0STakashi Iwai  * Returns true if a matching path is found.
451dda42bd0STakashi Iwai  *
452dda42bd0STakashi Iwai  * The parsing behavior depends on parameters:
453352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4543ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4553ca529d3STakashi Iwai  * with the given value are evaluated.
4563ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4573ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4583ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
459352f7f91STakashi Iwai  */
460c4a58c30STakashi Iwai static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4613ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
462352f7f91STakashi Iwai 			    struct nid_path *path)
463352f7f91STakashi Iwai {
4643ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
465352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
466352f7f91STakashi Iwai 		path->depth++;
467352f7f91STakashi Iwai 		return true;
468352f7f91STakashi Iwai 	}
469352f7f91STakashi Iwai 	return false;
470352f7f91STakashi Iwai }
471352f7f91STakashi Iwai 
472dda42bd0STakashi Iwai /**
473dda42bd0STakashi Iwai  * snd_hda_add_new_path - parse the path between the given NIDs and
474dda42bd0STakashi Iwai  * add to the path list
475dda42bd0STakashi Iwai  * @codec: the HDA codec
476dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
477dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
478dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
479dda42bd0STakashi Iwai  *
480dda42bd0STakashi Iwai  * If no valid path is found, returns NULL.
481352f7f91STakashi Iwai  */
482352f7f91STakashi Iwai struct nid_path *
483352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4843ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
485352f7f91STakashi Iwai {
486352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
487352f7f91STakashi Iwai 	struct nid_path *path;
488352f7f91STakashi Iwai 
489352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
490352f7f91STakashi Iwai 		return NULL;
491352f7f91STakashi Iwai 
492f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4933ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
494f5172a7eSTakashi Iwai 	if (path)
495f5172a7eSTakashi Iwai 		return path;
496f5172a7eSTakashi Iwai 
497352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
498352f7f91STakashi Iwai 	if (!path)
499352f7f91STakashi Iwai 		return NULL;
500352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
5013ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
502352f7f91STakashi Iwai 		return path;
503352f7f91STakashi Iwai 	/* push back */
504352f7f91STakashi Iwai 	spec->paths.used--;
505352f7f91STakashi Iwai 	return NULL;
506352f7f91STakashi Iwai }
5072698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
508352f7f91STakashi Iwai 
509980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
510980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
511980428ceSTakashi Iwai {
512980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
513980428ceSTakashi Iwai 	if (!path)
514980428ceSTakashi Iwai 		return;
515980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
516980428ceSTakashi Iwai }
517980428ceSTakashi Iwai 
5183690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
5193690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
5203690739bSTakashi Iwai {
5213690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5223690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
5233690739bSTakashi Iwai 
5243690739bSTakashi Iwai 	if (!list)
5253690739bSTakashi Iwai 		return 0;
5263690739bSTakashi Iwai 	for (; *list; list += 2)
5273690739bSTakashi Iwai 		if (*list == pin)
5283690739bSTakashi Iwai 			return list[1];
5293690739bSTakashi Iwai 	return 0;
5303690739bSTakashi Iwai }
5313690739bSTakashi Iwai 
532352f7f91STakashi Iwai /* look for an empty DAC slot */
533352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
534352f7f91STakashi Iwai 			      bool is_digital)
535352f7f91STakashi Iwai {
536352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
537352f7f91STakashi Iwai 	bool cap_digital;
538352f7f91STakashi Iwai 	int i;
539352f7f91STakashi Iwai 
540352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
541352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
542352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
543352f7f91STakashi Iwai 			continue;
544352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
545352f7f91STakashi Iwai 		if (is_digital != cap_digital)
546352f7f91STakashi Iwai 			continue;
547352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
548352f7f91STakashi Iwai 			return nid;
549352f7f91STakashi Iwai 	}
550352f7f91STakashi Iwai 	return 0;
551352f7f91STakashi Iwai }
552352f7f91STakashi Iwai 
553352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
554352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
555352f7f91STakashi Iwai {
556352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
557352f7f91STakashi Iwai 	val |= chs << 16;
558352f7f91STakashi Iwai 	return val;
559352f7f91STakashi Iwai }
560352f7f91STakashi Iwai 
56199a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
56299a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
56399a5592dSDavid Henningsson {
56499a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
56599a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
56699a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
56799a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
56899a5592dSDavid Henningsson }
56999a5592dSDavid Henningsson 
570352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
571352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
572352f7f91STakashi Iwai 				       struct nid_path *path)
573352f7f91STakashi Iwai {
574352f7f91STakashi Iwai 	int i;
575352f7f91STakashi Iwai 
576352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
577352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
578352f7f91STakashi Iwai 			return path->path[i];
579352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
580352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
581352f7f91STakashi Iwai 			return path->path[i];
582352f7f91STakashi Iwai 	}
583352f7f91STakashi Iwai 	return 0;
584352f7f91STakashi Iwai }
585352f7f91STakashi Iwai 
586352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
587352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
588352f7f91STakashi Iwai 				      struct nid_path *path)
589352f7f91STakashi Iwai {
590a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
591352f7f91STakashi Iwai 	int i;
592352f7f91STakashi Iwai 
593352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
594a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
595a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
596a1114a8cSTakashi Iwai 			continue;
597a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
598a1114a8cSTakashi Iwai 			return nid;
599352f7f91STakashi Iwai 	}
600352f7f91STakashi Iwai 	return 0;
601352f7f91STakashi Iwai }
602352f7f91STakashi Iwai 
603352f7f91STakashi Iwai /*
604352f7f91STakashi Iwai  * path activation / deactivation
605352f7f91STakashi Iwai  */
606352f7f91STakashi Iwai 
607352f7f91STakashi Iwai /* can have the amp-in capability? */
608352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
609352f7f91STakashi Iwai {
610352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
611352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
612352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
613352f7f91STakashi Iwai 
614352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
615352f7f91STakashi Iwai 		return false;
616352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
617352f7f91STakashi Iwai 		return false;
618352f7f91STakashi Iwai 	return true;
619352f7f91STakashi Iwai }
620352f7f91STakashi Iwai 
621352f7f91STakashi Iwai /* can have the amp-out capability? */
622352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
623352f7f91STakashi Iwai {
624352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
625352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
626352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
627352f7f91STakashi Iwai 
628352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
629352f7f91STakashi Iwai 		return false;
630352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
631352f7f91STakashi Iwai 		return false;
632352f7f91STakashi Iwai 	return true;
633352f7f91STakashi Iwai }
634352f7f91STakashi Iwai 
635352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
636352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6377dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
638352f7f91STakashi Iwai {
639352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
640e6feb5d0STakashi Iwai 	int type = get_wcaps_type(get_wcaps(codec, nid));
641352f7f91STakashi Iwai 	int i, n;
642352f7f91STakashi Iwai 
6437639a06cSTakashi Iwai 	if (nid == codec->core.afg)
6445ccf835cSTakashi Iwai 		return true;
6455ccf835cSTakashi Iwai 
646352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
647352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
648352f7f91STakashi Iwai 		if (!path->active)
649352f7f91STakashi Iwai 			continue;
650967b1307STakashi Iwai 		if (codec->power_save_node) {
651e6feb5d0STakashi Iwai 			if (!path->stream_enabled)
652e6feb5d0STakashi Iwai 				continue;
653e6feb5d0STakashi Iwai 			/* ignore unplugged paths except for DAC/ADC */
6546b275b14STakashi Iwai 			if (!(path->pin_enabled || path->pin_fixed) &&
655e6feb5d0STakashi Iwai 			    type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
656e6feb5d0STakashi Iwai 				continue;
657e6feb5d0STakashi Iwai 		}
658352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
659352f7f91STakashi Iwai 			if (path->path[i] == nid) {
6609d2b48f7STakashi Iwai 				if (dir == HDA_OUTPUT || idx == -1 ||
6619d2b48f7STakashi Iwai 				    path->idx[i] == idx)
662352f7f91STakashi Iwai 					return true;
663352f7f91STakashi Iwai 				break;
664352f7f91STakashi Iwai 			}
665352f7f91STakashi Iwai 		}
666352f7f91STakashi Iwai 	}
667352f7f91STakashi Iwai 	return false;
668352f7f91STakashi Iwai }
669352f7f91STakashi Iwai 
670b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
671b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
6729d2b48f7STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, -1)
673b1b9fbd0STakashi Iwai 
674352f7f91STakashi Iwai /* get the default amp value for the target state */
675352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6768999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
677352f7f91STakashi Iwai {
678352f7f91STakashi Iwai 	unsigned int val = 0;
679352f7f91STakashi Iwai 
680352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
681352f7f91STakashi Iwai 		/* set to 0dB */
682352f7f91STakashi Iwai 		if (enable)
683352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
684352f7f91STakashi Iwai 	}
685f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
686352f7f91STakashi Iwai 		if (!enable)
687352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
688352f7f91STakashi Iwai 	}
689352f7f91STakashi Iwai 	return val;
690352f7f91STakashi Iwai }
691352f7f91STakashi Iwai 
692cc261738STakashi Iwai /* is this a stereo widget or a stereo-to-mono mix? */
693cc261738STakashi Iwai static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
694cc261738STakashi Iwai {
695cc261738STakashi Iwai 	unsigned int wcaps = get_wcaps(codec, nid);
696cc261738STakashi Iwai 	hda_nid_t conn;
697cc261738STakashi Iwai 
698cc261738STakashi Iwai 	if (wcaps & AC_WCAP_STEREO)
699cc261738STakashi Iwai 		return true;
700cc261738STakashi Iwai 	if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
701cc261738STakashi Iwai 		return false;
702cc261738STakashi Iwai 	if (snd_hda_get_num_conns(codec, nid) != 1)
703cc261738STakashi Iwai 		return false;
704cc261738STakashi Iwai 	if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
705cc261738STakashi Iwai 		return false;
706cc261738STakashi Iwai 	return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
707cc261738STakashi Iwai }
708cc261738STakashi Iwai 
709352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
710352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
711352f7f91STakashi Iwai {
7128999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
7138999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
714ef403edbSTakashi Iwai 
715cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
716352f7f91STakashi Iwai 		snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
717ef403edbSTakashi Iwai 	else
718ef403edbSTakashi Iwai 		snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
719ef403edbSTakashi Iwai }
720ef403edbSTakashi Iwai 
721ef403edbSTakashi Iwai /* update the amp, doing in stereo or mono depending on NID */
722ef403edbSTakashi Iwai static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
723ef403edbSTakashi Iwai 		      unsigned int mask, unsigned int val)
724ef403edbSTakashi Iwai {
725cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
726ef403edbSTakashi Iwai 		return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
727ef403edbSTakashi Iwai 						mask, val);
728ef403edbSTakashi Iwai 	else
729ef403edbSTakashi Iwai 		return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
730ef403edbSTakashi Iwai 						mask, val);
731352f7f91STakashi Iwai }
732352f7f91STakashi Iwai 
7338999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
7348999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
7358999bf0aSTakashi Iwai  */
7368999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
7378999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
7388999bf0aSTakashi Iwai 					   unsigned int caps)
739352f7f91STakashi Iwai {
7408999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
7418999bf0aSTakashi Iwai 
742f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
7438999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
7448999bf0aSTakashi Iwai 			mask &= ~0x80;
7458999bf0aSTakashi Iwai 	}
7468999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
7478999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
7488999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
7498999bf0aSTakashi Iwai 			mask &= ~0x7f;
7508999bf0aSTakashi Iwai 	}
7518999bf0aSTakashi Iwai 	return mask;
7528999bf0aSTakashi Iwai }
7538999bf0aSTakashi Iwai 
7548999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
7558999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
7568999bf0aSTakashi Iwai {
7578999bf0aSTakashi Iwai 	unsigned int caps;
7588999bf0aSTakashi Iwai 	unsigned int mask, val;
7598999bf0aSTakashi Iwai 
7608999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
7618999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
7628999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
7638999bf0aSTakashi Iwai 	if (!mask)
7648999bf0aSTakashi Iwai 		return;
7658999bf0aSTakashi Iwai 
7668999bf0aSTakashi Iwai 	val &= mask;
767ef403edbSTakashi Iwai 	update_amp(codec, nid, dir, idx, mask, val);
768352f7f91STakashi Iwai }
769352f7f91STakashi Iwai 
770e7fdd527STakashi Iwai static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
771e7fdd527STakashi Iwai 				   int dir, int idx, int idx_to_check,
772e7fdd527STakashi Iwai 				   bool enable)
773e7fdd527STakashi Iwai {
774e7fdd527STakashi Iwai 	/* check whether the given amp is still used by others */
775e7fdd527STakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
776e7fdd527STakashi Iwai 		return;
777e7fdd527STakashi Iwai 	activate_amp(codec, nid, dir, idx, idx_to_check, enable);
778e7fdd527STakashi Iwai }
779e7fdd527STakashi Iwai 
780352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
781352f7f91STakashi Iwai 			     int i, bool enable)
782352f7f91STakashi Iwai {
783352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
784352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
785e7fdd527STakashi Iwai 	check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
786352f7f91STakashi Iwai }
787352f7f91STakashi Iwai 
788352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
789352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
790352f7f91STakashi Iwai {
791352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
792ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
793352f7f91STakashi Iwai 	int n, nums, idx;
794352f7f91STakashi Iwai 	int type;
795352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
796352f7f91STakashi Iwai 
797ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
798352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
799352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
800352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
801352f7f91STakashi Iwai 		nums = 1;
802352f7f91STakashi Iwai 		idx = 0;
803352f7f91STakashi Iwai 	} else
804352f7f91STakashi Iwai 		idx = path->idx[i];
805352f7f91STakashi Iwai 
806352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
807352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
808352f7f91STakashi Iwai 
809352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
810352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
811352f7f91STakashi Iwai 	 */
812352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
813e7fdd527STakashi Iwai 		if (n != idx) {
814e7fdd527STakashi Iwai 			if (conn[n] != spec->mixer_merge_nid)
815352f7f91STakashi Iwai 				continue;
816e7fdd527STakashi Iwai 			/* when aamix is disabled, force to off */
817e7fdd527STakashi Iwai 			if (!add_aamix) {
818e7fdd527STakashi Iwai 				activate_amp(codec, nid, HDA_INPUT, n, n, false);
819e7fdd527STakashi Iwai 				continue;
820e7fdd527STakashi Iwai 			}
821e7fdd527STakashi Iwai 		}
822e7fdd527STakashi Iwai 		check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
823352f7f91STakashi Iwai 	}
824352f7f91STakashi Iwai }
825352f7f91STakashi Iwai 
826e6feb5d0STakashi Iwai /* sync power of each widget in the the given path */
827e6feb5d0STakashi Iwai static hda_nid_t path_power_update(struct hda_codec *codec,
828e6feb5d0STakashi Iwai 				   struct nid_path *path,
829e6feb5d0STakashi Iwai 				   bool allow_powerdown)
830e6feb5d0STakashi Iwai {
831e6feb5d0STakashi Iwai 	hda_nid_t nid, changed = 0;
83250fd4987STakashi Iwai 	int i, state, power;
833e6feb5d0STakashi Iwai 
834e6feb5d0STakashi Iwai 	for (i = 0; i < path->depth; i++) {
835e6feb5d0STakashi Iwai 		nid = path->path[i];
8362206dc94STakashi Iwai 		if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
8372206dc94STakashi Iwai 			continue;
8387639a06cSTakashi Iwai 		if (nid == codec->core.afg)
8395ccf835cSTakashi Iwai 			continue;
840e6feb5d0STakashi Iwai 		if (!allow_powerdown || is_active_nid_for_any(codec, nid))
841e6feb5d0STakashi Iwai 			state = AC_PWRST_D0;
842e6feb5d0STakashi Iwai 		else
843e6feb5d0STakashi Iwai 			state = AC_PWRST_D3;
84450fd4987STakashi Iwai 		power = snd_hda_codec_read(codec, nid, 0,
84550fd4987STakashi Iwai 					   AC_VERB_GET_POWER_STATE, 0);
84650fd4987STakashi Iwai 		if (power != (state | (state << 4))) {
847e6feb5d0STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
848e6feb5d0STakashi Iwai 					    AC_VERB_SET_POWER_STATE, state);
849e6feb5d0STakashi Iwai 			changed = nid;
85048f4b3a2STakashi Iwai 			/* all known codecs seem to be capable to handl
85148f4b3a2STakashi Iwai 			 * widgets state even in D3, so far.
85248f4b3a2STakashi Iwai 			 * if any new codecs need to restore the widget
85348f4b3a2STakashi Iwai 			 * states after D0 transition, call the function
85448f4b3a2STakashi Iwai 			 * below.
85548f4b3a2STakashi Iwai 			 */
85648f4b3a2STakashi Iwai #if 0 /* disabled */
857d545a57cSTakashi Iwai 			if (state == AC_PWRST_D0)
858d545a57cSTakashi Iwai 				snd_hdac_regmap_sync_node(&codec->core, nid);
85948f4b3a2STakashi Iwai #endif
860e6feb5d0STakashi Iwai 		}
861e6feb5d0STakashi Iwai 	}
862e6feb5d0STakashi Iwai 	return changed;
863e6feb5d0STakashi Iwai }
864e6feb5d0STakashi Iwai 
865e6feb5d0STakashi Iwai /* do sync with the last power state change */
866e6feb5d0STakashi Iwai static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
867e6feb5d0STakashi Iwai {
868e6feb5d0STakashi Iwai 	if (nid) {
869e6feb5d0STakashi Iwai 		msleep(10);
870e6feb5d0STakashi Iwai 		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
871e6feb5d0STakashi Iwai 	}
872e6feb5d0STakashi Iwai }
873e6feb5d0STakashi Iwai 
874dda42bd0STakashi Iwai /**
875dda42bd0STakashi Iwai  * snd_hda_activate_path - activate or deactivate the given path
876dda42bd0STakashi Iwai  * @codec: the HDA codec
877dda42bd0STakashi Iwai  * @path: the path to activate/deactivate
878dda42bd0STakashi Iwai  * @enable: flag to activate or not
879dda42bd0STakashi Iwai  * @add_aamix: enable the input from aamix NID
880dda42bd0STakashi Iwai  *
881dda42bd0STakashi Iwai  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
882352f7f91STakashi Iwai  */
883352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
884352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
885352f7f91STakashi Iwai {
88655196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
887352f7f91STakashi Iwai 	int i;
888352f7f91STakashi Iwai 
889c7cd0ef6STakashi Iwai 	path->active = enable;
890352f7f91STakashi Iwai 
891e6feb5d0STakashi Iwai 	/* make sure the widget is powered up */
892967b1307STakashi Iwai 	if (enable && (spec->power_down_unused || codec->power_save_node))
893967b1307STakashi Iwai 		path_power_update(codec, path, codec->power_save_node);
894e6feb5d0STakashi Iwai 
895352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
89655196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
897e6feb5d0STakashi Iwai 
898352f7f91STakashi Iwai 		if (enable && path->multi[i])
8998f0972dfSTakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
900352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
901352f7f91STakashi Iwai 					    path->idx[i]);
902352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
903352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
904352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
905352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
906352f7f91STakashi Iwai 	}
907352f7f91STakashi Iwai }
9082698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
909352f7f91STakashi Iwai 
91055196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
91155196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
91255196fffSTakashi Iwai {
91355196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
91455196fffSTakashi Iwai 
915967b1307STakashi Iwai 	if (!(spec->power_down_unused || codec->power_save_node) || path->active)
91655196fffSTakashi Iwai 		return;
917e6feb5d0STakashi Iwai 	sync_power_state_change(codec, path_power_update(codec, path, true));
91855196fffSTakashi Iwai }
91955196fffSTakashi Iwai 
920d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
921d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
922d5a9f1bbSTakashi Iwai {
923d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
924d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
925d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
926d5a9f1bbSTakashi Iwai 		return;
92705909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
92805909d5cSTakashi Iwai 		return;
929468ac413STakashi Iwai 	if (codec->inv_eapd)
930468ac413STakashi Iwai 		enable = !enable;
931d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
932d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
933d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
934d5a9f1bbSTakashi Iwai }
935d5a9f1bbSTakashi Iwai 
9363e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
9373e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
9383e367f15STakashi Iwai {
9393e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
9403e367f15STakashi Iwai 	if (path)
9413e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
9423e367f15STakashi Iwai }
9433e367f15STakashi Iwai 
944352f7f91STakashi Iwai 
945352f7f91STakashi Iwai /*
946352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
947352f7f91STakashi Iwai  */
948352f7f91STakashi Iwai 
9497eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
9507eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
951bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
952bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
9537eebffd3STakashi Iwai 
954352f7f91STakashi Iwai enum {
955352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
956352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
957352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
958352f7f91STakashi Iwai };
959352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
960352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
9617eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
9627eebffd3STakashi Iwai 	{
9637eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9647eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
9657eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
9667eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
9677eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
9687eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
9697eebffd3STakashi Iwai 	},
970bc2eee29STakashi Iwai 	{
971bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
972bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
973bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
974bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
975bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
976bc2eee29STakashi Iwai 	},
977352f7f91STakashi Iwai };
978352f7f91STakashi Iwai 
979352f7f91STakashi Iwai /* add dynamic controls from template */
980a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
981a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
982352f7f91STakashi Iwai 		       int cidx, unsigned long val)
983352f7f91STakashi Iwai {
984352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
985352f7f91STakashi Iwai 
98612c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
987352f7f91STakashi Iwai 	if (!knew)
988a35bd1e3STakashi Iwai 		return NULL;
989352f7f91STakashi Iwai 	knew->index = cidx;
990352f7f91STakashi Iwai 	if (get_amp_nid_(val))
991352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
992352f7f91STakashi Iwai 	knew->private_value = val;
993a35bd1e3STakashi Iwai 	return knew;
994352f7f91STakashi Iwai }
995352f7f91STakashi Iwai 
996352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
997352f7f91STakashi Iwai 				const char *pfx, const char *dir,
998352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
999352f7f91STakashi Iwai {
1000975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1001352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
1002a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
1003a35bd1e3STakashi Iwai 		return -ENOMEM;
1004a35bd1e3STakashi Iwai 	return 0;
1005352f7f91STakashi Iwai }
1006352f7f91STakashi Iwai 
1007352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1008352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1009352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1010352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1011352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1012352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1013352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1014352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1015352f7f91STakashi Iwai 
1016352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1017352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
1018352f7f91STakashi Iwai {
1019352f7f91STakashi Iwai 	unsigned int val;
1020352f7f91STakashi Iwai 	if (!path)
1021352f7f91STakashi Iwai 		return 0;
1022352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
1023352f7f91STakashi Iwai 	if (!val)
1024352f7f91STakashi Iwai 		return 0;
1025352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1026352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1027352f7f91STakashi Iwai }
1028352f7f91STakashi Iwai 
1029352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
1030352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1031352f7f91STakashi Iwai 			       int type)
1032352f7f91STakashi Iwai {
1033352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
1034352f7f91STakashi Iwai 	if (path) {
1035352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1036352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1037352f7f91STakashi Iwai 			chs = 3; /* stereo */
1038352f7f91STakashi Iwai 	}
1039352f7f91STakashi Iwai 	return chs;
1040352f7f91STakashi Iwai }
1041352f7f91STakashi Iwai 
1042352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1043352f7f91STakashi Iwai 			  struct nid_path *path)
1044352f7f91STakashi Iwai {
1045352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1046352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1047352f7f91STakashi Iwai }
1048352f7f91STakashi Iwai 
1049352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
1050352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1051352f7f91STakashi Iwai  */
1052352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1053352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
1054352f7f91STakashi Iwai {
1055352f7f91STakashi Iwai 	unsigned int val;
1056352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
1057352f7f91STakashi Iwai 
1058352f7f91STakashi Iwai 	if (!path)
1059352f7f91STakashi Iwai 		return 0;
1060352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
1061352f7f91STakashi Iwai 	if (!val)
1062352f7f91STakashi Iwai 		return 0;
1063352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1064352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
1065352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
1066352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
1067352f7f91STakashi Iwai 		if (nums > 1) {
1068352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
1069352f7f91STakashi Iwai 			val |= nums << 19;
1070352f7f91STakashi Iwai 		}
1071352f7f91STakashi Iwai 	}
1072352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1073352f7f91STakashi Iwai }
1074352f7f91STakashi Iwai 
1075352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1076352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1077352f7f91STakashi Iwai {
1078352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1079352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1080352f7f91STakashi Iwai }
1081352f7f91STakashi Iwai 
10827eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1083bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10847eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10857eebffd3STakashi Iwai {
10867eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10877eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10887eebffd3STakashi Iwai 
10897eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10907eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10917eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10927eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10937eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10947eebffd3STakashi Iwai 	}
1095bc2eee29STakashi Iwai }
10967eebffd3STakashi Iwai 
1097bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1098bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1099bc2eee29STakashi Iwai {
1100bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
11017eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
11027eebffd3STakashi Iwai }
11037eebffd3STakashi Iwai 
1104bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1105bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1106bc2eee29STakashi Iwai {
1107bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1108bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
1109bc2eee29STakashi Iwai }
1110bc2eee29STakashi Iwai 
1111247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1112247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1113247d85eeSTakashi Iwai {
1114247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1115247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1116247d85eeSTakashi Iwai }
1117247d85eeSTakashi Iwai 
1118352f7f91STakashi Iwai static const char * const channel_name[4] = {
1119352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1120352f7f91STakashi Iwai };
1121352f7f91STakashi Iwai 
1122352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1123247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1124247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1125352f7f91STakashi Iwai {
1126247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1127352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1128352f7f91STakashi Iwai 
1129352f7f91STakashi Iwai 	*index = 0;
1130352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
11319f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1132247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1133352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1134352f7f91STakashi Iwai 
1135352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1136352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1137352f7f91STakashi Iwai 	 */
1138352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
11399f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1140352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1141352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1142352f7f91STakashi Iwai 
1143247d85eeSTakashi Iwai 	/* multi-io channels */
1144247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1145247d85eeSTakashi Iwai 		return channel_name[ch];
1146247d85eeSTakashi Iwai 
1147352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1148352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1149247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1150247d85eeSTakashi Iwai 		 * don't name it as Speaker
1151247d85eeSTakashi Iwai 		 */
1152247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1153247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1154247d85eeSTakashi Iwai 			break;
1155352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1156352f7f91STakashi Iwai 			return "Speaker";
1157352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1158352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1159352f7f91STakashi Iwai 		break;
1160352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1161247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1162247d85eeSTakashi Iwai 		 * don't name it as Headphone
1163247d85eeSTakashi Iwai 		 */
1164247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1165247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1166247d85eeSTakashi Iwai 			break;
1167352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1168352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1169352f7f91STakashi Iwai 			break;
1170352f7f91STakashi Iwai 		*index = ch;
1171352f7f91STakashi Iwai 		return "Headphone";
117203ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
117303ad6a8cSDavid Henningsson 		/* This deals with the case where we have two DACs and
117403ad6a8cSDavid Henningsson 		 * one LO, one HP and one Speaker */
117503ad6a8cSDavid Henningsson 		if (!ch && cfg->speaker_outs && cfg->hp_outs) {
117603ad6a8cSDavid Henningsson 			bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
117703ad6a8cSDavid Henningsson 			bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
117803ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
117903ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
118003ad6a8cSDavid Henningsson 			if (hp_lo_shared)
118103ad6a8cSDavid Henningsson 				return "Headphone+LO";
118203ad6a8cSDavid Henningsson 			if (spk_lo_shared)
118303ad6a8cSDavid Henningsson 				return "Speaker+LO";
118403ad6a8cSDavid Henningsson 		}
1185247d85eeSTakashi Iwai 	}
1186247d85eeSTakashi Iwai 
1187247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1188352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
11893abb4f4dSDavid Henningsson 		return "Line Out";
1190247d85eeSTakashi Iwai 
1191352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1192352f7f91STakashi Iwai 		snd_BUG();
1193352f7f91STakashi Iwai 		return "PCM";
1194352f7f91STakashi Iwai 	}
1195352f7f91STakashi Iwai 
1196352f7f91STakashi Iwai 	return channel_name[ch];
1197352f7f91STakashi Iwai }
1198352f7f91STakashi Iwai 
1199352f7f91STakashi Iwai /*
1200352f7f91STakashi Iwai  * Parse output paths
1201352f7f91STakashi Iwai  */
1202352f7f91STakashi Iwai 
1203352f7f91STakashi Iwai /* badness definition */
1204352f7f91STakashi Iwai enum {
1205352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1206352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1207352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1208352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1209352f7f91STakashi Iwai 	/* No possible multi-ios */
12101d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1211352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1212352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1213352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1214352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1215352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1216352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
121755a63d4dSTakashi Iwai 	/* No independent HP possible */
1218bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1219352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1220352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1221352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1222352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1223352f7f91STakashi Iwai 	/* Volume widget is shared */
1224352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1225352f7f91STakashi Iwai };
1226352f7f91STakashi Iwai 
12270e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1228352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1229352f7f91STakashi Iwai  *
1230352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1231352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1232352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1233352f7f91STakashi Iwai  */
12340e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1235352f7f91STakashi Iwai {
1236d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1237352f7f91STakashi Iwai 	hda_nid_t nid;
1238352f7f91STakashi Iwai 	unsigned int val;
1239352f7f91STakashi Iwai 	int badness = 0;
1240352f7f91STakashi Iwai 
1241352f7f91STakashi Iwai 	if (!path)
1242352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
12430e614dd0STakashi Iwai 
12440e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
12450e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
12460e614dd0STakashi Iwai 		return 0; /* already evaluated */
12470e614dd0STakashi Iwai 
1248352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1249352f7f91STakashi Iwai 	if (nid) {
1250352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1251d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1252d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1253352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1254352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1255352f7f91STakashi Iwai 		else
1256352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1257352f7f91STakashi Iwai 	} else
1258352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1259352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1260352f7f91STakashi Iwai 	if (nid) {
1261352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1262352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1263352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1264352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1265352f7f91STakashi Iwai 		else
1266352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1267352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1268352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1269352f7f91STakashi Iwai 		else
1270352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1271352f7f91STakashi Iwai 	} else
1272352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1273352f7f91STakashi Iwai 	return badness;
1274352f7f91STakashi Iwai }
1275352f7f91STakashi Iwai 
127698bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1277352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1278352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1279352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1280352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1281352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1282352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1283352f7f91STakashi Iwai };
12842698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1285352f7f91STakashi Iwai 
128698bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1287352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1288352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1289352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1290352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1291352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1292352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1293352f7f91STakashi Iwai };
12942698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1295352f7f91STakashi Iwai 
12967385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
12977385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
12987385df61STakashi Iwai {
12997385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
13007385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
13017385df61STakashi Iwai 
13027385df61STakashi Iwai 	if (cfg->line_outs > idx)
13037385df61STakashi Iwai 		return spec->private_dac_nids[idx];
13047385df61STakashi Iwai 	idx -= cfg->line_outs;
13057385df61STakashi Iwai 	if (spec->multi_ios > idx)
13067385df61STakashi Iwai 		return spec->multi_io[idx].dac;
13077385df61STakashi Iwai 	return 0;
13087385df61STakashi Iwai }
13097385df61STakashi Iwai 
13107385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
13117385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
13127385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
13137385df61STakashi Iwai {
13147385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
13157385df61STakashi Iwai }
13167385df61STakashi Iwai 
1317352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1318352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1319352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1320196c1766STakashi Iwai 			   int *path_idx,
1321352f7f91STakashi Iwai 			   const struct badness_table *bad)
1322352f7f91STakashi Iwai {
1323352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1324352f7f91STakashi Iwai 	int i, j;
1325352f7f91STakashi Iwai 	int badness = 0;
1326352f7f91STakashi Iwai 	hda_nid_t dac;
1327352f7f91STakashi Iwai 
1328352f7f91STakashi Iwai 	if (!num_outs)
1329352f7f91STakashi Iwai 		return 0;
1330352f7f91STakashi Iwai 
1331352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
13320c8c0f56STakashi Iwai 		struct nid_path *path;
1333352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
13341e0b5286STakashi Iwai 
13350e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
13360e614dd0STakashi Iwai 		if (path) {
13370e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
13381e0b5286STakashi Iwai 			continue;
13391e0b5286STakashi Iwai 		}
13401e0b5286STakashi Iwai 
13413690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
13423690739bSTakashi Iwai 		if (dacs[i]) {
13433690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
13443690739bSTakashi Iwai 				badness += bad->shared_primary;
13453690739bSTakashi Iwai 		}
13463690739bSTakashi Iwai 
13473690739bSTakashi Iwai 		if (!dacs[i])
1348352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1349352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1350980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1351352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1352352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1353352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1354352f7f91STakashi Iwai 					dacs[j] = 0;
1355980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1356196c1766STakashi Iwai 					path_idx[j] = 0;
1357352f7f91STakashi Iwai 					break;
1358352f7f91STakashi Iwai 				}
1359352f7f91STakashi Iwai 			}
1360352f7f91STakashi Iwai 		}
1361352f7f91STakashi Iwai 		dac = dacs[i];
1362352f7f91STakashi Iwai 		if (!dac) {
13637385df61STakashi Iwai 			if (num_outs > 2)
13647385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
13657385df61STakashi Iwai 			if (!dac)
13667385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
13677385df61STakashi Iwai 			if (!dac)
13687385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1369352f7f91STakashi Iwai 			if (dac) {
1370352f7f91STakashi Iwai 				if (!i)
1371352f7f91STakashi Iwai 					badness += bad->shared_primary;
1372352f7f91STakashi Iwai 				else if (i == 1)
1373352f7f91STakashi Iwai 					badness += bad->shared_surr;
1374352f7f91STakashi Iwai 				else
1375352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1376352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1377352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1378352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1379352f7f91STakashi Iwai 			} else if (!i)
1380352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1381352f7f91STakashi Iwai 			else
1382352f7f91STakashi Iwai 				badness += bad->no_dac;
1383352f7f91STakashi Iwai 		}
13841fa335b0STakashi Iwai 		if (!dac)
13851fa335b0STakashi Iwai 			continue;
13863ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1387117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1388b3a8c745STakashi Iwai 			/* try with aamix */
13893ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1390b3a8c745STakashi Iwai 		}
13911fa335b0STakashi Iwai 		if (!path) {
1392352f7f91STakashi Iwai 			dac = dacs[i] = 0;
13931fa335b0STakashi Iwai 			badness += bad->no_dac;
13941fa335b0STakashi Iwai 		} else {
13954e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1396e1284af7STakashi Iwai 			path->active = true;
1397196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
13980e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1399e1284af7STakashi Iwai 		}
1400352f7f91STakashi Iwai 	}
1401352f7f91STakashi Iwai 
1402352f7f91STakashi Iwai 	return badness;
1403352f7f91STakashi Iwai }
1404352f7f91STakashi Iwai 
1405352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1406352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1407352f7f91STakashi Iwai {
1408352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1409352f7f91STakashi Iwai 	int i;
1410352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1411352f7f91STakashi Iwai 
1412352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1413352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1414352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1415352f7f91STakashi Iwai 			continue;
1416352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1417352f7f91STakashi Iwai 			if (nid_found)
1418352f7f91STakashi Iwai 				return 0;
1419352f7f91STakashi Iwai 			nid_found = nid;
1420352f7f91STakashi Iwai 		}
1421352f7f91STakashi Iwai 	}
1422352f7f91STakashi Iwai 	return nid_found;
1423352f7f91STakashi Iwai }
1424352f7f91STakashi Iwai 
1425352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1426352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1427352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1428352f7f91STakashi Iwai {
1429352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1430352f7f91STakashi Iwai 
1431352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1432352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1433352f7f91STakashi Iwai 		return false;
1434352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1435352f7f91STakashi Iwai 		return false;
1436352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1437352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1438352f7f91STakashi Iwai 		return false;
1439352f7f91STakashi Iwai 	return true;
1440352f7f91STakashi Iwai }
1441352f7f91STakashi Iwai 
1442e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1443e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1444e22aab7dSTakashi Iwai {
1445e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1446e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1447e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1448e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1449e22aab7dSTakashi Iwai 	int type, i;
1450e22aab7dSTakashi Iwai 	int num_pins = 0;
1451e22aab7dSTakashi Iwai 
1452e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1453e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1454e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1455e22aab7dSTakashi Iwai 				continue;
1456e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1457e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1458e22aab7dSTakashi Iwai 				num_pins++;
1459e22aab7dSTakashi Iwai 		}
1460e22aab7dSTakashi Iwai 	}
1461e22aab7dSTakashi Iwai 	return num_pins;
1462e22aab7dSTakashi Iwai }
1463e22aab7dSTakashi Iwai 
1464352f7f91STakashi Iwai /*
1465352f7f91STakashi Iwai  * multi-io helper
1466352f7f91STakashi Iwai  *
1467352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1468352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1469352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1470352f7f91STakashi Iwai  * the badness value.
1471352f7f91STakashi Iwai  */
1472352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1473352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1474e22aab7dSTakashi Iwai 			  bool hardwired)
1475352f7f91STakashi Iwai {
1476352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1477352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1478e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1479352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1480352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1481352f7f91STakashi Iwai 	int badness = 0;
14820e614dd0STakashi Iwai 	struct nid_path *path;
1483352f7f91STakashi Iwai 
1484352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1485352f7f91STakashi Iwai 	if (old_pins >= 2)
1486352f7f91STakashi Iwai 		goto end_fill;
1487352f7f91STakashi Iwai 
1488e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1489352f7f91STakashi Iwai 	if (num_pins < 2)
1490352f7f91STakashi Iwai 		goto end_fill;
1491352f7f91STakashi Iwai 
1492352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1493352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1494352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1495352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1496352f7f91STakashi Iwai 
1497352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1498352f7f91STakashi Iwai 				continue;
1499352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1500352f7f91STakashi Iwai 				continue;
1501352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1502352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1503352f7f91STakashi Iwai 					break;
1504352f7f91STakashi Iwai 			}
1505352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1506352f7f91STakashi Iwai 				continue;
1507352f7f91STakashi Iwai 
1508352f7f91STakashi Iwai 			if (hardwired)
1509352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1510352f7f91STakashi Iwai 			else if (!dac)
1511352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1512352f7f91STakashi Iwai 			if (!dac) {
1513352f7f91STakashi Iwai 				badness++;
1514352f7f91STakashi Iwai 				continue;
1515352f7f91STakashi Iwai 			}
15163ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
15173ca529d3STakashi Iwai 						    -spec->mixer_nid);
15180c8c0f56STakashi Iwai 			if (!path) {
1519352f7f91STakashi Iwai 				badness++;
1520352f7f91STakashi Iwai 				continue;
1521352f7f91STakashi Iwai 			}
15224e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1523352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1524352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1525196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1526196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1527352f7f91STakashi Iwai 			spec->multi_ios++;
1528352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1529352f7f91STakashi Iwai 				break;
1530352f7f91STakashi Iwai 		}
1531352f7f91STakashi Iwai 	}
1532352f7f91STakashi Iwai  end_fill:
1533352f7f91STakashi Iwai 	if (badness)
1534352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1535352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1536352f7f91STakashi Iwai 		if (hardwired)
1537352f7f91STakashi Iwai 			return 1; /* nothing found */
1538352f7f91STakashi Iwai 		else
1539352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1540352f7f91STakashi Iwai 	}
1541352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1542352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1543352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1544352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1545352f7f91STakashi Iwai 		return badness;
1546352f7f91STakashi Iwai 	}
1547352f7f91STakashi Iwai 
1548352f7f91STakashi Iwai 	/* assign volume and mute controls */
15490e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
15500e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
15510e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
15520e614dd0STakashi Iwai 	}
1553352f7f91STakashi Iwai 
1554352f7f91STakashi Iwai 	return badness;
1555352f7f91STakashi Iwai }
1556352f7f91STakashi Iwai 
1557352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1558352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1559196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1560352f7f91STakashi Iwai {
1561b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1562352f7f91STakashi Iwai 	int i;
1563352f7f91STakashi Iwai 	bool found = false;
1564352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
15650c8c0f56STakashi Iwai 		struct nid_path *path;
1566352f7f91STakashi Iwai 		hda_nid_t dac;
1567352f7f91STakashi Iwai 		if (dacs[i])
1568352f7f91STakashi Iwai 			continue;
1569352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1570352f7f91STakashi Iwai 		if (!dac)
1571352f7f91STakashi Iwai 			continue;
15723ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
15733ca529d3STakashi Iwai 					    -spec->mixer_nid);
1574117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
15753ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
15760c8c0f56STakashi Iwai 		if (path) {
1577352f7f91STakashi Iwai 			dacs[i] = dac;
1578352f7f91STakashi Iwai 			found = true;
15794e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1580e1284af7STakashi Iwai 			path->active = true;
1581196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1582352f7f91STakashi Iwai 		}
1583352f7f91STakashi Iwai 	}
1584352f7f91STakashi Iwai 	return found;
1585352f7f91STakashi Iwai }
1586352f7f91STakashi Iwai 
1587e7fdd527STakashi Iwai static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1588e7fdd527STakashi Iwai {
1589e7fdd527STakashi Iwai 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1590e7fdd527STakashi Iwai 		spec->aamix_out_paths[2];
1591e7fdd527STakashi Iwai }
1592e7fdd527STakashi Iwai 
1593c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1594c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1595c30aa7b2STakashi Iwai {
15963ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1597c30aa7b2STakashi Iwai 	struct nid_path *path;
15985ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1599c30aa7b2STakashi Iwai 
1600c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
16013ca529d3STakashi Iwai 	if (!path || !path->depth ||
16023ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1603c30aa7b2STakashi Iwai 		return 0;
16045ead56f2STakashi Iwai 	path_dac = path->path[0];
16055ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1606f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1607f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1608f87498b6STakashi Iwai 	if (!path) {
16095ead56f2STakashi Iwai 		if (dac != path_dac)
16105ead56f2STakashi Iwai 			dac = path_dac;
1611f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1612f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1613f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1614f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
16155ead56f2STakashi Iwai 		else
16165ead56f2STakashi Iwai 			dac = 0;
1617f87498b6STakashi Iwai 		if (dac)
1618f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
16193ca529d3STakashi Iwai 						    spec->mixer_nid);
1620f87498b6STakashi Iwai 	}
1621c30aa7b2STakashi Iwai 	if (!path)
1622c30aa7b2STakashi Iwai 		return 0;
16234e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1624c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
16256b275b14STakashi Iwai 	path->pin_fixed = true; /* static route */
1626c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1627c30aa7b2STakashi Iwai }
1628c30aa7b2STakashi Iwai 
162955a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
163055a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
163155a63d4dSTakashi Iwai {
163255a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
163355a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
163455a63d4dSTakashi Iwai 	struct nid_path *path;
163555a63d4dSTakashi Iwai 	int i, idx;
163655a63d4dSTakashi Iwai 
163755a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
163855a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
163955a63d4dSTakashi Iwai 	else
164055a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
164155a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
164255a63d4dSTakashi Iwai 	if (!path)
164355a63d4dSTakashi Iwai 		return false;
164455a63d4dSTakashi Iwai 
164555a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
164655a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
164755a63d4dSTakashi Iwai 		return true;
164855a63d4dSTakashi Iwai 
164955a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
165055a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
165155a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
165255a63d4dSTakashi Iwai 			break;
165355a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
165455a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
165555a63d4dSTakashi Iwai 			return false;
165655a63d4dSTakashi Iwai 	}
165755a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
165855a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
165955a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
166055a63d4dSTakashi Iwai 			return false;
166155a63d4dSTakashi Iwai 	}
166255a63d4dSTakashi Iwai 
166355a63d4dSTakashi Iwai 	return true;
166455a63d4dSTakashi Iwai }
166555a63d4dSTakashi Iwai 
1666a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1667a07a949bSTakashi Iwai  * shared dac pointed by the paths
1668a07a949bSTakashi Iwai  */
1669a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1670a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1671a07a949bSTakashi Iwai {
1672a07a949bSTakashi Iwai 	struct nid_path *path;
1673a07a949bSTakashi Iwai 	int i;
1674a07a949bSTakashi Iwai 
1675a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1676a07a949bSTakashi Iwai 		if (dacs[i])
1677a07a949bSTakashi Iwai 			continue;
1678a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1679a07a949bSTakashi Iwai 		if (!path)
1680a07a949bSTakashi Iwai 			continue;
1681a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1682a07a949bSTakashi Iwai 	}
1683a07a949bSTakashi Iwai }
1684a07a949bSTakashi Iwai 
1685352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1686352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1687352f7f91STakashi Iwai 			      bool fill_hardwired,
1688352f7f91STakashi Iwai 			      bool fill_mio_first)
1689352f7f91STakashi Iwai {
1690352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1691352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1692352f7f91STakashi Iwai 	int i, err, badness;
1693352f7f91STakashi Iwai 
1694352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1695352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1696352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1697352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1698352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1699352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1700352f7f91STakashi Iwai 	spec->multi_ios = 0;
1701352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1702cd5be3f9STakashi Iwai 
1703cd5be3f9STakashi Iwai 	/* clear path indices */
1704cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1705cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1706cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1707cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1708cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1709c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1710cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1711cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1712cd5be3f9STakashi Iwai 
1713352f7f91STakashi Iwai 	badness = 0;
1714352f7f91STakashi Iwai 
1715352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1716352f7f91STakashi Iwai 	if (fill_hardwired) {
1717352f7f91STakashi Iwai 		bool mapped;
1718352f7f91STakashi Iwai 		do {
1719352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1720352f7f91STakashi Iwai 					     cfg->line_out_pins,
1721196c1766STakashi Iwai 					     spec->private_dac_nids,
1722196c1766STakashi Iwai 					     spec->out_paths);
1723352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1724352f7f91STakashi Iwai 					      cfg->hp_pins,
1725196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1726196c1766STakashi Iwai 					      spec->hp_paths);
1727352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1728352f7f91STakashi Iwai 					      cfg->speaker_pins,
1729196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1730196c1766STakashi Iwai 					      spec->speaker_paths);
1731da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1732da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1733352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1734e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1735352f7f91STakashi Iwai 				if (!err)
1736352f7f91STakashi Iwai 					mapped = true;
1737352f7f91STakashi Iwai 			}
1738352f7f91STakashi Iwai 		} while (mapped);
1739352f7f91STakashi Iwai 	}
1740352f7f91STakashi Iwai 
1741352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1742196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
174398bd1115STakashi Iwai 				   spec->main_out_badness);
1744352f7f91STakashi Iwai 
1745da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1746352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1747352f7f91STakashi Iwai 		/* try to fill multi-io first */
1748e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1749352f7f91STakashi Iwai 		if (err < 0)
1750352f7f91STakashi Iwai 			return err;
1751352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1752352f7f91STakashi Iwai 	}
1753352f7f91STakashi Iwai 
1754352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1755352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1756352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1757196c1766STakashi Iwai 				      spec->hp_paths,
175898bd1115STakashi Iwai 				      spec->extra_out_badness);
1759352f7f91STakashi Iwai 		if (err < 0)
1760352f7f91STakashi Iwai 			return err;
1761352f7f91STakashi Iwai 		badness += err;
1762352f7f91STakashi Iwai 	}
1763352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1764352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1765352f7f91STakashi Iwai 				      cfg->speaker_pins,
1766352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1767196c1766STakashi Iwai 				      spec->speaker_paths,
176898bd1115STakashi Iwai 				      spec->extra_out_badness);
1769352f7f91STakashi Iwai 		if (err < 0)
1770352f7f91STakashi Iwai 			return err;
1771352f7f91STakashi Iwai 		badness += err;
1772352f7f91STakashi Iwai 	}
1773da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1774da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1775e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1776352f7f91STakashi Iwai 		if (err < 0)
1777352f7f91STakashi Iwai 			return err;
1778352f7f91STakashi Iwai 		badness += err;
1779352f7f91STakashi Iwai 	}
1780e22aab7dSTakashi Iwai 
1781c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1782c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1783c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1784c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1785c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1786c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1787c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1788c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1789c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1790c30aa7b2STakashi Iwai 	}
1791c30aa7b2STakashi Iwai 
1792da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1793da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1794e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1795e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1796352f7f91STakashi Iwai 
1797a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1798a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1799a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1800a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1801a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1802a07a949bSTakashi Iwai 		else {
1803a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1804a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1805a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1806a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1807a07a949bSTakashi Iwai 		}
1808a07a949bSTakashi Iwai 	}
1809a07a949bSTakashi Iwai 
1810a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1811c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1812a07a949bSTakashi Iwai 
1813352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1814352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1815352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1816352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1817352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1818352f7f91STakashi Iwai 		spec->multi_ios = 0;
1819352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1820352f7f91STakashi Iwai 	}
1821352f7f91STakashi Iwai 
182255a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
182355a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
182455a63d4dSTakashi Iwai 
1825a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1826a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1827a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1828a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1829a07a949bSTakashi Iwai 				   spec->hp_paths);
1830a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1831a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1832a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1833a07a949bSTakashi Iwai 				   spec->speaker_paths);
1834a07a949bSTakashi Iwai 
1835352f7f91STakashi Iwai 	return badness;
1836352f7f91STakashi Iwai }
1837352f7f91STakashi Iwai 
1838352f7f91STakashi Iwai #define DEBUG_BADNESS
1839352f7f91STakashi Iwai 
1840352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1841d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1842d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1843352f7f91STakashi Iwai #else
1844d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1845d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1846352f7f91STakashi Iwai #endif
1847352f7f91STakashi Iwai 
1848a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1849a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1850a769409cSTakashi Iwai 				      const char *pfx, int idx)
1851352f7f91STakashi Iwai {
1852a769409cSTakashi Iwai 	struct nid_path *path;
1853a769409cSTakashi Iwai 
1854a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1855a769409cSTakashi Iwai 	if (path)
18564e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1857a769409cSTakashi Iwai }
1858a769409cSTakashi Iwai 
1859a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1860a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1861a769409cSTakashi Iwai {
1862a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1863a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1864a769409cSTakashi Iwai 	int i;
1865a769409cSTakashi Iwai 
1866a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1867352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1868708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1869352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1870352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1871352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1872a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1873a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1874a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1875a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1876352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1877352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1878352f7f91STakashi Iwai 			      spec->multi_ios,
1879352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1880352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1881a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1882a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1883a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1884a769409cSTakashi Iwai 	if (cfg->hp_outs)
1885352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1886352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1887708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1888352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1889352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1890352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1891352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1892a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1893a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1894a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1895352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1896352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1897352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1898352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1899352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1900352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1901352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1902a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1903a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1904a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1905a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1906352f7f91STakashi Iwai }
1907a769409cSTakashi Iwai #else
1908a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1909a769409cSTakashi Iwai #endif
1910352f7f91STakashi Iwai 
1911352f7f91STakashi Iwai /* find all available DACs of the codec */
1912352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1913352f7f91STakashi Iwai {
1914352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
19157639a06cSTakashi Iwai 	hda_nid_t nid;
1916352f7f91STakashi Iwai 
1917352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1918352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
19197639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
1920352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1921352f7f91STakashi Iwai 			continue;
1922352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
19234e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1924352f7f91STakashi Iwai 			break;
1925352f7f91STakashi Iwai 		}
1926352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1927352f7f91STakashi Iwai 	}
1928352f7f91STakashi Iwai }
1929352f7f91STakashi Iwai 
1930352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1931352f7f91STakashi Iwai {
1932352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1933352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1934352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
19359314a581STakashi Iwai 	unsigned int val;
1936352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1937352f7f91STakashi Iwai 	int badness;
1938352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1939352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1940352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1941352f7f91STakashi Iwai 
1942352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1943352f7f91STakashi Iwai 	if (!best_cfg)
1944352f7f91STakashi Iwai 		return -ENOMEM;
1945352f7f91STakashi Iwai 	*best_cfg = *cfg;
1946352f7f91STakashi Iwai 
1947352f7f91STakashi Iwai 	for (;;) {
1948352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1949352f7f91STakashi Iwai 					     fill_mio_first);
1950352f7f91STakashi Iwai 		if (badness < 0) {
1951352f7f91STakashi Iwai 			kfree(best_cfg);
1952352f7f91STakashi Iwai 			return badness;
1953352f7f91STakashi Iwai 		}
1954352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1955352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1956352f7f91STakashi Iwai 			      badness);
1957a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1958352f7f91STakashi Iwai 		if (badness < best_badness) {
1959352f7f91STakashi Iwai 			best_badness = badness;
1960352f7f91STakashi Iwai 			*best_cfg = *cfg;
1961352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1962352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1963352f7f91STakashi Iwai 		}
1964352f7f91STakashi Iwai 		if (!badness)
1965352f7f91STakashi Iwai 			break;
1966352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1967352f7f91STakashi Iwai 		if (!fill_mio_first)
1968352f7f91STakashi Iwai 			continue;
1969352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1970352f7f91STakashi Iwai 		if (!fill_hardwired)
1971352f7f91STakashi Iwai 			continue;
1972352f7f91STakashi Iwai 		if (hp_spk_swapped)
1973352f7f91STakashi Iwai 			break;
1974352f7f91STakashi Iwai 		hp_spk_swapped = true;
1975352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1976352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1977352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1978352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1979352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1980352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1981352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1982352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1983352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1984352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1985352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1986352f7f91STakashi Iwai 			fill_hardwired = true;
1987352f7f91STakashi Iwai 			continue;
1988352f7f91STakashi Iwai 		}
1989352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1990352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1991352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1992352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1993352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1994352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1995352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1996352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1997352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1998352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1999352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
2000352f7f91STakashi Iwai 			fill_hardwired = true;
2001352f7f91STakashi Iwai 			continue;
2002352f7f91STakashi Iwai 		}
2003352f7f91STakashi Iwai 		break;
2004352f7f91STakashi Iwai 	}
2005352f7f91STakashi Iwai 
2006352f7f91STakashi Iwai 	if (badness) {
20070c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
2008352f7f91STakashi Iwai 		*cfg = *best_cfg;
2009352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
2010352f7f91STakashi Iwai 	}
2011352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2012352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
2013a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
2014352f7f91STakashi Iwai 
2015352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
2016352f7f91STakashi Iwai 		struct nid_path *path;
2017196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2018352f7f91STakashi Iwai 		if (path)
2019352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2020d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
20217a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
20227a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
2023d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
2024d89c6c0cSTakashi Iwai 				spec->vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
2025d89c6c0cSTakashi Iwai 		}
2026352f7f91STakashi Iwai 	}
2027352f7f91STakashi Iwai 
20289314a581STakashi Iwai 	/* set initial pinctl targets */
20299314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
20309314a581STakashi Iwai 		val = PIN_HP;
20319314a581STakashi Iwai 	else
20329314a581STakashi Iwai 		val = PIN_OUT;
20339314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
20349314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
20359314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
20369314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
20379314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
20389314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
20399314a581STakashi Iwai 				cfg->speaker_pins, val);
20409314a581STakashi Iwai 	}
20419314a581STakashi Iwai 
204255a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
204355a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
204455a63d4dSTakashi Iwai 		spec->indep_hp = 0;
204555a63d4dSTakashi Iwai 
2046352f7f91STakashi Iwai 	kfree(best_cfg);
2047352f7f91STakashi Iwai 	return 0;
2048352f7f91STakashi Iwai }
2049352f7f91STakashi Iwai 
2050352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
2051352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
2052352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
2053352f7f91STakashi Iwai {
2054352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2055352f7f91STakashi Iwai 	int i, err, noutputs;
2056352f7f91STakashi Iwai 
2057352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
2058352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2059352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
2060352f7f91STakashi Iwai 
2061352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
2062352f7f91STakashi Iwai 		const char *name;
2063352f7f91STakashi Iwai 		int index;
2064352f7f91STakashi Iwai 		struct nid_path *path;
2065352f7f91STakashi Iwai 
2066196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2067352f7f91STakashi Iwai 		if (!path)
2068352f7f91STakashi Iwai 			continue;
2069247d85eeSTakashi Iwai 
2070247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2071352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2072352f7f91STakashi Iwai 			/* Center/LFE */
2073352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2074352f7f91STakashi Iwai 			if (err < 0)
2075352f7f91STakashi Iwai 				return err;
2076352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2077352f7f91STakashi Iwai 			if (err < 0)
2078352f7f91STakashi Iwai 				return err;
2079247d85eeSTakashi Iwai 		} else {
2080247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2081247d85eeSTakashi Iwai 			if (err < 0)
2082247d85eeSTakashi Iwai 				return err;
2083247d85eeSTakashi Iwai 		}
2084247d85eeSTakashi Iwai 
2085247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2086247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2087352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2088352f7f91STakashi Iwai 			if (err < 0)
2089352f7f91STakashi Iwai 				return err;
2090352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2091352f7f91STakashi Iwai 			if (err < 0)
2092352f7f91STakashi Iwai 				return err;
2093352f7f91STakashi Iwai 		} else {
2094352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2095352f7f91STakashi Iwai 			if (err < 0)
2096352f7f91STakashi Iwai 				return err;
2097352f7f91STakashi Iwai 		}
2098352f7f91STakashi Iwai 	}
2099352f7f91STakashi Iwai 	return 0;
2100352f7f91STakashi Iwai }
2101352f7f91STakashi Iwai 
2102c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2103196c1766STakashi Iwai 			    const char *pfx, int cidx)
2104352f7f91STakashi Iwai {
2105352f7f91STakashi Iwai 	struct nid_path *path;
2106352f7f91STakashi Iwai 	int err;
2107352f7f91STakashi Iwai 
2108196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2109352f7f91STakashi Iwai 	if (!path)
2110352f7f91STakashi Iwai 		return 0;
2111352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2112352f7f91STakashi Iwai 	if (err < 0)
2113352f7f91STakashi Iwai 		return err;
2114352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2115352f7f91STakashi Iwai 	if (err < 0)
2116352f7f91STakashi Iwai 		return err;
2117352f7f91STakashi Iwai 	return 0;
2118352f7f91STakashi Iwai }
2119352f7f91STakashi Iwai 
2120352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2121352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2122196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2123352f7f91STakashi Iwai {
2124c2c80383STakashi Iwai 	int i;
2125352f7f91STakashi Iwai 
2126352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2127c2c80383STakashi Iwai 		const char *name;
2128975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2129c2c80383STakashi Iwai 		int err, idx = 0;
2130c2c80383STakashi Iwai 
2131c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2132c2c80383STakashi Iwai 			name = "Bass Speaker";
2133c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2134c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2135352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2136c2c80383STakashi Iwai 			name = tmp;
2137352f7f91STakashi Iwai 		} else {
2138c2c80383STakashi Iwai 			name = pfx;
2139c2c80383STakashi Iwai 			idx = i;
2140352f7f91STakashi Iwai 		}
2141c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2142352f7f91STakashi Iwai 		if (err < 0)
2143352f7f91STakashi Iwai 			return err;
2144352f7f91STakashi Iwai 	}
2145352f7f91STakashi Iwai 	return 0;
2146352f7f91STakashi Iwai }
2147352f7f91STakashi Iwai 
2148352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2149352f7f91STakashi Iwai {
2150352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2151352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2152196c1766STakashi Iwai 				 spec->hp_paths,
2153352f7f91STakashi Iwai 				 "Headphone");
2154352f7f91STakashi Iwai }
2155352f7f91STakashi Iwai 
2156352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2157352f7f91STakashi Iwai {
2158352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2159352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2160196c1766STakashi Iwai 				 spec->speaker_paths,
2161352f7f91STakashi Iwai 				 "Speaker");
2162352f7f91STakashi Iwai }
2163352f7f91STakashi Iwai 
2164352f7f91STakashi Iwai /*
216538cf6f1aSTakashi Iwai  * independent HP controls
216638cf6f1aSTakashi Iwai  */
216738cf6f1aSTakashi Iwai 
21681a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
21691a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
217038cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
217138cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
217238cf6f1aSTakashi Iwai {
217338cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
217438cf6f1aSTakashi Iwai }
217538cf6f1aSTakashi Iwai 
217638cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
217738cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
217838cf6f1aSTakashi Iwai {
217938cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
218038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
218138cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
218238cf6f1aSTakashi Iwai 	return 0;
218338cf6f1aSTakashi Iwai }
218438cf6f1aSTakashi Iwai 
2185a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2186a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2187a1e908edSTakashi Iwai 			       int out_type);
2188a1e908edSTakashi Iwai 
218938cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
219038cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
219138cf6f1aSTakashi Iwai {
219238cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
219338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
219438cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
219538cf6f1aSTakashi Iwai 	int ret = 0;
219638cf6f1aSTakashi Iwai 
219738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
219838cf6f1aSTakashi Iwai 	if (spec->active_streams) {
219938cf6f1aSTakashi Iwai 		ret = -EBUSY;
220038cf6f1aSTakashi Iwai 		goto unlock;
220138cf6f1aSTakashi Iwai 	}
220238cf6f1aSTakashi Iwai 
220338cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2204a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2205a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2206a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2207a1e908edSTakashi Iwai 		else
2208a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2209a1e908edSTakashi Iwai 
2210a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2211a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2212a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2213a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2214a1e908edSTakashi Iwai 						   spec->out_paths[0],
2215a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2216a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2217a1e908edSTakashi Iwai 			else
2218a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2219a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2220a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2221a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2222a1e908edSTakashi Iwai 		}
2223a1e908edSTakashi Iwai 
222438cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
222538cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2226a1e908edSTakashi Iwai 			*dacp = 0;
222738cf6f1aSTakashi Iwai 		else
2228a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
222992603c59STakashi Iwai 
2230963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
223138cf6f1aSTakashi Iwai 		ret = 1;
223238cf6f1aSTakashi Iwai 	}
223338cf6f1aSTakashi Iwai  unlock:
223438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
223538cf6f1aSTakashi Iwai 	return ret;
223638cf6f1aSTakashi Iwai }
223738cf6f1aSTakashi Iwai 
223838cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
223938cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
224038cf6f1aSTakashi Iwai 	.name = "Independent HP",
224138cf6f1aSTakashi Iwai 	.info = indep_hp_info,
224238cf6f1aSTakashi Iwai 	.get = indep_hp_get,
224338cf6f1aSTakashi Iwai 	.put = indep_hp_put,
224438cf6f1aSTakashi Iwai };
224538cf6f1aSTakashi Iwai 
224638cf6f1aSTakashi Iwai 
224738cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
224838cf6f1aSTakashi Iwai {
224938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2250a1e908edSTakashi Iwai 	hda_nid_t dac;
225138cf6f1aSTakashi Iwai 
225238cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
225338cf6f1aSTakashi Iwai 		return 0;
2254a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2255a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2256a1e908edSTakashi Iwai 	else
2257a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2258a1e908edSTakashi Iwai 	if (!dac) {
225938cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
226038cf6f1aSTakashi Iwai 		return 0;
226138cf6f1aSTakashi Iwai 	}
226238cf6f1aSTakashi Iwai 
226338cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2264a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
226538cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
226638cf6f1aSTakashi Iwai 		return -ENOMEM;
226738cf6f1aSTakashi Iwai 	return 0;
226838cf6f1aSTakashi Iwai }
226938cf6f1aSTakashi Iwai 
227038cf6f1aSTakashi Iwai /*
2271352f7f91STakashi Iwai  * channel mode enum control
2272352f7f91STakashi Iwai  */
2273352f7f91STakashi Iwai 
2274352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2275352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2276352f7f91STakashi Iwai {
2277352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2278352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2279a07a949bSTakashi Iwai 	int chs;
2280352f7f91STakashi Iwai 
2281352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2282352f7f91STakashi Iwai 	uinfo->count = 1;
2283352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2284352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2285352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2286a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2287a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2288352f7f91STakashi Iwai 	return 0;
2289352f7f91STakashi Iwai }
2290352f7f91STakashi Iwai 
2291352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2292352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2293352f7f91STakashi Iwai {
2294352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2295352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2296a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2297a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2298352f7f91STakashi Iwai 	return 0;
2299352f7f91STakashi Iwai }
2300352f7f91STakashi Iwai 
2301196c1766STakashi Iwai static inline struct nid_path *
2302196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2303196c1766STakashi Iwai {
2304196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2305196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2306196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2307196c1766STakashi Iwai }
2308196c1766STakashi Iwai 
2309a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2310a5cc2509STakashi Iwai 
231165033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
231265033cc8STakashi Iwai  * used for output paths
231365033cc8STakashi Iwai  */
231465033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
231565033cc8STakashi Iwai {
231665033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
231765033cc8STakashi Iwai }
231865033cc8STakashi Iwai 
2319352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2320352f7f91STakashi Iwai {
2321352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2322352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2323352f7f91STakashi Iwai 	struct nid_path *path;
2324352f7f91STakashi Iwai 
2325196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2326352f7f91STakashi Iwai 	if (!path)
2327352f7f91STakashi Iwai 		return -EINVAL;
2328352f7f91STakashi Iwai 
2329352f7f91STakashi Iwai 	if (path->active == output)
2330352f7f91STakashi Iwai 		return 0;
2331352f7f91STakashi Iwai 
2332352f7f91STakashi Iwai 	if (output) {
23332c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
233465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2335d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2336352f7f91STakashi Iwai 	} else {
2337d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
233865033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
23392c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
234055196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2341352f7f91STakashi Iwai 	}
2342a365fed9STakashi Iwai 
2343a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2344a5cc2509STakashi Iwai 	update_automute_all(codec);
2345a365fed9STakashi Iwai 
2346352f7f91STakashi Iwai 	return 0;
2347352f7f91STakashi Iwai }
2348352f7f91STakashi Iwai 
2349352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2350352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2351352f7f91STakashi Iwai {
2352352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2353352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2354352f7f91STakashi Iwai 	int i, ch;
2355352f7f91STakashi Iwai 
2356352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2357352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2358352f7f91STakashi Iwai 		return -EINVAL;
2359a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2360352f7f91STakashi Iwai 		return 0;
2361a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2362352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2363352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2364352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2365352f7f91STakashi Iwai 					  spec->const_channel_count);
2366352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2367352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2368352f7f91STakashi Iwai 	return 1;
2369352f7f91STakashi Iwai }
2370352f7f91STakashi Iwai 
2371352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2372352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2373352f7f91STakashi Iwai 	.name = "Channel Mode",
2374352f7f91STakashi Iwai 	.info = ch_mode_info,
2375352f7f91STakashi Iwai 	.get = ch_mode_get,
2376352f7f91STakashi Iwai 	.put = ch_mode_put,
2377352f7f91STakashi Iwai };
2378352f7f91STakashi Iwai 
2379352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2380352f7f91STakashi Iwai {
2381352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2382352f7f91STakashi Iwai 
2383352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
238412c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2385352f7f91STakashi Iwai 			return -ENOMEM;
2386352f7f91STakashi Iwai 	}
2387352f7f91STakashi Iwai 	return 0;
2388352f7f91STakashi Iwai }
2389352f7f91STakashi Iwai 
2390352f7f91STakashi Iwai /*
2391c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2392c30aa7b2STakashi Iwai  */
2393c30aa7b2STakashi Iwai 
2394c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2395c30aa7b2STakashi Iwai 
2396c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2397c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2398c30aa7b2STakashi Iwai {
2399c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2400c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2401c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2402c30aa7b2STakashi Iwai 	return 0;
2403c30aa7b2STakashi Iwai }
2404c30aa7b2STakashi Iwai 
2405c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2406a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2407a1e908edSTakashi Iwai 			       int out_type)
2408c30aa7b2STakashi Iwai {
2409a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2410c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2411c30aa7b2STakashi Iwai 
2412c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2413c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2414c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2415c30aa7b2STakashi Iwai 		return;
2416a1e908edSTakashi Iwai 
2417a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2418a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2419a1e908edSTakashi Iwai 	 */
2420a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2421a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2422a1e908edSTakashi Iwai 		do_mix = false;
2423a1e908edSTakashi Iwai 
2424c30aa7b2STakashi Iwai 	if (do_mix) {
2425c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2426c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
242755196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2428c30aa7b2STakashi Iwai 	} else {
242965033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
243065033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
243155196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2432c30aa7b2STakashi Iwai 	}
2433c30aa7b2STakashi Iwai }
2434c30aa7b2STakashi Iwai 
2435e7fdd527STakashi Iwai /* re-initialize the output paths; only called from loopback_mixing_put() */
2436e7fdd527STakashi Iwai static void update_output_paths(struct hda_codec *codec, int num_outs,
2437e7fdd527STakashi Iwai 				const int *paths)
2438e7fdd527STakashi Iwai {
2439e7fdd527STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2440e7fdd527STakashi Iwai 	struct nid_path *path;
2441e7fdd527STakashi Iwai 	int i;
2442e7fdd527STakashi Iwai 
2443e7fdd527STakashi Iwai 	for (i = 0; i < num_outs; i++) {
2444e7fdd527STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2445e7fdd527STakashi Iwai 		if (path)
2446e7fdd527STakashi Iwai 			snd_hda_activate_path(codec, path, path->active,
2447e7fdd527STakashi Iwai 					      spec->aamix_mode);
2448e7fdd527STakashi Iwai 	}
2449e7fdd527STakashi Iwai }
2450e7fdd527STakashi Iwai 
2451c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2452c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2453c30aa7b2STakashi Iwai {
2454c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2455c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2456e7fdd527STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2457c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2458c30aa7b2STakashi Iwai 
2459c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2460c30aa7b2STakashi Iwai 		return 0;
2461c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2462e7fdd527STakashi Iwai 	if (has_aamix_out_paths(spec)) {
2463c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->out_paths[0],
2464a1e908edSTakashi Iwai 				   spec->aamix_out_paths[0],
2465e7fdd527STakashi Iwai 				   cfg->line_out_type);
2466c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->hp_paths[0],
2467a1e908edSTakashi Iwai 				   spec->aamix_out_paths[1],
2468a1e908edSTakashi Iwai 				   AUTO_PIN_HP_OUT);
2469c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2470a1e908edSTakashi Iwai 				   spec->aamix_out_paths[2],
2471a1e908edSTakashi Iwai 				   AUTO_PIN_SPEAKER_OUT);
2472e7fdd527STakashi Iwai 	} else {
2473e7fdd527STakashi Iwai 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2474e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2475e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2476e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2477e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->speaker_outs,
2478e7fdd527STakashi Iwai 					    spec->speaker_paths);
2479e7fdd527STakashi Iwai 	}
2480c30aa7b2STakashi Iwai 	return 1;
2481c30aa7b2STakashi Iwai }
2482c30aa7b2STakashi Iwai 
2483c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2484c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2485c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2486c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2487c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2488c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2489c30aa7b2STakashi Iwai };
2490c30aa7b2STakashi Iwai 
2491c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2492c30aa7b2STakashi Iwai {
2493c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2494c30aa7b2STakashi Iwai 
2495c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2496c30aa7b2STakashi Iwai 		return 0;
2497c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2498c30aa7b2STakashi Iwai 		return -ENOMEM;
2499a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2500c30aa7b2STakashi Iwai 	return 0;
2501c30aa7b2STakashi Iwai }
2502c30aa7b2STakashi Iwai 
2503c30aa7b2STakashi Iwai /*
2504352f7f91STakashi Iwai  * shared headphone/mic handling
2505352f7f91STakashi Iwai  */
2506352f7f91STakashi Iwai 
2507352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2508352f7f91STakashi Iwai 
2509352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2510967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2511352f7f91STakashi Iwai {
2512352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2513967303daSTakashi Iwai 	bool as_mic;
2514352f7f91STakashi Iwai 	unsigned int val;
2515967303daSTakashi Iwai 	hda_nid_t pin;
2516967303daSTakashi Iwai 
2517967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2518967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2519967303daSTakashi Iwai 
2520967303daSTakashi Iwai 	if (!force) {
2521967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2522967303daSTakashi Iwai 		if (as_mic) {
2523967303daSTakashi Iwai 			if (val & PIN_IN)
2524967303daSTakashi Iwai 				return;
2525967303daSTakashi Iwai 		} else {
2526967303daSTakashi Iwai 			if (val & PIN_OUT)
2527967303daSTakashi Iwai 				return;
2528967303daSTakashi Iwai 		}
2529967303daSTakashi Iwai 	}
2530352f7f91STakashi Iwai 
2531352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2532967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2533967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2534967303daSTakashi Iwai 	 */
2535352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2536352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2537352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2538352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
25397594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2540967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2541352f7f91STakashi Iwai 	}
2542352f7f91STakashi Iwai 
25438ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2544967303daSTakashi Iwai 		if (as_mic)
2545967303daSTakashi Iwai 			val |= PIN_IN;
2546967303daSTakashi Iwai 		else
2547967303daSTakashi Iwai 			val = PIN_HP;
25482c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2549963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
25508ba955ceSTakashi Iwai 	}
2551352f7f91STakashi Iwai }
2552352f7f91STakashi Iwai 
2553352f7f91STakashi Iwai /* create a shared input with the headphone out */
2554967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2555352f7f91STakashi Iwai {
2556352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2557352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2558352f7f91STakashi Iwai 	unsigned int defcfg;
2559352f7f91STakashi Iwai 	hda_nid_t nid;
2560352f7f91STakashi Iwai 
2561967303daSTakashi Iwai 	if (!spec->hp_mic) {
2562967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2563352f7f91STakashi Iwai 			return 0;
2564967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2565967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2566967303daSTakashi Iwai 		 */
2567967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2568967303daSTakashi Iwai 			return 0;
2569967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2570352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2571352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2572352f7f91STakashi Iwai 				return 0;
2573967303daSTakashi Iwai 		}
2574967303daSTakashi Iwai 	}
2575352f7f91STakashi Iwai 
2576967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2577967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2578967303daSTakashi Iwai 		return 0;
2579967303daSTakashi Iwai 
2580967303daSTakashi Iwai 	nid = 0;
2581967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2582967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2583967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2584967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2585967303daSTakashi Iwai 	if (!nid)
2586967303daSTakashi Iwai 		return 0;
2587352f7f91STakashi Iwai 
2588352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2589352f7f91STakashi Iwai 		return 0; /* no input */
2590352f7f91STakashi Iwai 
2591967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2592967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2593cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2594967303daSTakashi Iwai 	cfg->num_inputs++;
2595967303daSTakashi Iwai 	spec->hp_mic = 1;
2596967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2597967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2598967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
25994e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2600352f7f91STakashi Iwai 	return 0;
2601352f7f91STakashi Iwai }
2602352f7f91STakashi Iwai 
2603978e77e7STakashi Iwai /*
2604978e77e7STakashi Iwai  * output jack mode
2605978e77e7STakashi Iwai  */
26065f171baaSTakashi Iwai 
26075f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
26085f171baaSTakashi Iwai 
26095f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
26105f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
26115f171baaSTakashi Iwai };
26125f171baaSTakashi Iwai 
2613978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2614978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2615978e77e7STakashi Iwai {
26165f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2617978e77e7STakashi Iwai }
2618978e77e7STakashi Iwai 
2619978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2620978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2621978e77e7STakashi Iwai {
2622978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2623978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2624978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2625978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2626978e77e7STakashi Iwai 	else
2627978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2628978e77e7STakashi Iwai 	return 0;
2629978e77e7STakashi Iwai }
2630978e77e7STakashi Iwai 
2631978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2632978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2633978e77e7STakashi Iwai {
2634978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2635978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2636978e77e7STakashi Iwai 	unsigned int val;
2637978e77e7STakashi Iwai 
2638978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2639978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2640978e77e7STakashi Iwai 		return 0;
2641978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2642978e77e7STakashi Iwai 	return 1;
2643978e77e7STakashi Iwai }
2644978e77e7STakashi Iwai 
2645978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2646978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2647978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2648978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2649978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2650978e77e7STakashi Iwai };
2651978e77e7STakashi Iwai 
2652978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2653978e77e7STakashi Iwai {
2654978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2655978e77e7STakashi Iwai 	int i;
2656978e77e7STakashi Iwai 
2657978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2658978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2659978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2660978e77e7STakashi Iwai 			return true;
2661978e77e7STakashi Iwai 	}
2662978e77e7STakashi Iwai 	return false;
2663978e77e7STakashi Iwai }
2664978e77e7STakashi Iwai 
2665978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2666978e77e7STakashi Iwai 			       char *name, size_t name_len)
2667978e77e7STakashi Iwai {
2668978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2669978e77e7STakashi Iwai 	int idx = 0;
2670978e77e7STakashi Iwai 
2671978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2672978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2673978e77e7STakashi Iwai 
2674978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2675978e77e7STakashi Iwai 		;
2676978e77e7STakashi Iwai }
2677978e77e7STakashi Iwai 
26785f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26795f171baaSTakashi Iwai {
26805f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2681f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
26825f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
26835f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
26845f171baaSTakashi Iwai 			return 2;
26855f171baaSTakashi Iwai 	}
26865f171baaSTakashi Iwai 	return 1;
26875f171baaSTakashi Iwai }
26885f171baaSTakashi Iwai 
2689978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2690978e77e7STakashi Iwai 				 hda_nid_t *pins)
2691978e77e7STakashi Iwai {
2692978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2693978e77e7STakashi Iwai 	int i;
2694978e77e7STakashi Iwai 
2695978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2696978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2697ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
26985f171baaSTakashi Iwai 			continue;
26995f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2700978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2701975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2702978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2703978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2704978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2705978e77e7STakashi Iwai 			if (!knew)
2706978e77e7STakashi Iwai 				return -ENOMEM;
2707978e77e7STakashi Iwai 			knew->private_value = pin;
2708978e77e7STakashi Iwai 		}
2709978e77e7STakashi Iwai 	}
2710978e77e7STakashi Iwai 
2711978e77e7STakashi Iwai 	return 0;
2712978e77e7STakashi Iwai }
2713978e77e7STakashi Iwai 
271429476558STakashi Iwai /*
271529476558STakashi Iwai  * input jack mode
271629476558STakashi Iwai  */
271729476558STakashi Iwai 
271829476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
271929476558STakashi Iwai #define NUM_VREFS	6
272029476558STakashi Iwai 
272129476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
272229476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
272329476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
272429476558STakashi Iwai };
272529476558STakashi Iwai 
272629476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
272729476558STakashi Iwai {
272829476558STakashi Iwai 	unsigned int pincap;
272929476558STakashi Iwai 
273029476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
273129476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
273229476558STakashi Iwai 	/* filter out unusual vrefs */
273329476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
273429476558STakashi Iwai 	return pincap;
273529476558STakashi Iwai }
273629476558STakashi Iwai 
273729476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
273829476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
273929476558STakashi Iwai {
274029476558STakashi Iwai 	unsigned int i, n = 0;
274129476558STakashi Iwai 
274229476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
274329476558STakashi Iwai 		if (vref_caps & (1 << i)) {
274429476558STakashi Iwai 			if (n == item_idx)
274529476558STakashi Iwai 				return i;
274629476558STakashi Iwai 			n++;
274729476558STakashi Iwai 		}
274829476558STakashi Iwai 	}
274929476558STakashi Iwai 	return 0;
275029476558STakashi Iwai }
275129476558STakashi Iwai 
275229476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
275329476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
275429476558STakashi Iwai {
275529476558STakashi Iwai 	unsigned int i, n = 0;
275629476558STakashi Iwai 
275729476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
275829476558STakashi Iwai 		if (i == idx)
275929476558STakashi Iwai 			return n;
276029476558STakashi Iwai 		if (vref_caps & (1 << i))
276129476558STakashi Iwai 			n++;
276229476558STakashi Iwai 	}
276329476558STakashi Iwai 	return 0;
276429476558STakashi Iwai }
276529476558STakashi Iwai 
276629476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
276729476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
276829476558STakashi Iwai {
276929476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
277029476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
277129476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
277229476558STakashi Iwai 
277329476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
277429476558STakashi Iwai 				 vref_texts);
277529476558STakashi Iwai 	/* set the right text */
277629476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
277729476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
277829476558STakashi Iwai 	return 0;
277929476558STakashi Iwai }
278029476558STakashi Iwai 
278129476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
278229476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
278329476558STakashi Iwai {
278429476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
278529476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
278629476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
278729476558STakashi Iwai 	unsigned int idx;
278829476558STakashi Iwai 
278929476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
279029476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
279129476558STakashi Iwai 	return 0;
279229476558STakashi Iwai }
279329476558STakashi Iwai 
279429476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
279529476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
279629476558STakashi Iwai {
279729476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
279829476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
279929476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
280029476558STakashi Iwai 	unsigned int val, idx;
280129476558STakashi Iwai 
280229476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
280329476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
280429476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
280529476558STakashi Iwai 		return 0;
280629476558STakashi Iwai 
280729476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
280829476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
280929476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
281029476558STakashi Iwai 	return 1;
281129476558STakashi Iwai }
281229476558STakashi Iwai 
281329476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
281429476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
281529476558STakashi Iwai 	.info = in_jack_mode_info,
281629476558STakashi Iwai 	.get = in_jack_mode_get,
281729476558STakashi Iwai 	.put = in_jack_mode_put,
281829476558STakashi Iwai };
281929476558STakashi Iwai 
28205f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
28215f171baaSTakashi Iwai {
28225f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28235f171baaSTakashi Iwai 	int nitems = 0;
2824f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
28255f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
28265f171baaSTakashi Iwai 	return nitems ? nitems : 1;
28275f171baaSTakashi Iwai }
28285f171baaSTakashi Iwai 
282929476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
283029476558STakashi Iwai {
283129476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
283229476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2833975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
28345f171baaSTakashi Iwai 	unsigned int defcfg;
28355f171baaSTakashi Iwai 
2836f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2837f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
283829476558STakashi Iwai 
283929476558STakashi Iwai 	/* no jack mode for fixed pins */
284029476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
284129476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
284229476558STakashi Iwai 		return 0;
284329476558STakashi Iwai 
284429476558STakashi Iwai 	/* no multiple vref caps? */
28455f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
284629476558STakashi Iwai 		return 0;
284729476558STakashi Iwai 
284829476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
284929476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
285029476558STakashi Iwai 	if (!knew)
285129476558STakashi Iwai 		return -ENOMEM;
285229476558STakashi Iwai 	knew->private_value = pin;
285329476558STakashi Iwai 	return 0;
285429476558STakashi Iwai }
285529476558STakashi Iwai 
28565f171baaSTakashi Iwai /*
28575f171baaSTakashi Iwai  * HP/mic shared jack mode
28585f171baaSTakashi Iwai  */
28595f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
28605f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
28615f171baaSTakashi Iwai {
28625f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28635f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
28645f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
28655f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
28665f171baaSTakashi Iwai 	const char *text = NULL;
28675f171baaSTakashi Iwai 	int idx;
28685f171baaSTakashi Iwai 
28695f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
28705f171baaSTakashi Iwai 	uinfo->count = 1;
28715f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
28725f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
28735f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
28745f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
28755f171baaSTakashi Iwai 	if (idx < out_jacks) {
28765f171baaSTakashi Iwai 		if (out_jacks > 1)
28775f171baaSTakashi Iwai 			text = out_jack_texts[idx];
28785f171baaSTakashi Iwai 		else
28795f171baaSTakashi Iwai 			text = "Headphone Out";
28805f171baaSTakashi Iwai 	} else {
28815f171baaSTakashi Iwai 		idx -= out_jacks;
28825f171baaSTakashi Iwai 		if (in_jacks > 1) {
28835f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
28845f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
28855f171baaSTakashi Iwai 		} else
28865f171baaSTakashi Iwai 			text = "Mic In";
28875f171baaSTakashi Iwai 	}
28885f171baaSTakashi Iwai 
28895f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
28905f171baaSTakashi Iwai 	return 0;
28915f171baaSTakashi Iwai }
28925f171baaSTakashi Iwai 
28935f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
28945f171baaSTakashi Iwai {
28955f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
28965f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
28975f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
28985f171baaSTakashi Iwai 	int idx = 0;
28995f171baaSTakashi Iwai 
29005f171baaSTakashi Iwai 	if (val & PIN_OUT) {
29015f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
29025f171baaSTakashi Iwai 			idx = 1;
29035f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
29045f171baaSTakashi Iwai 		idx = out_jacks;
29055f171baaSTakashi Iwai 		if (in_jacks > 1) {
29065f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29075f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
29085f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
29095f171baaSTakashi Iwai 		}
29105f171baaSTakashi Iwai 	}
29115f171baaSTakashi Iwai 	return idx;
29125f171baaSTakashi Iwai }
29135f171baaSTakashi Iwai 
29145f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
29155f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29165f171baaSTakashi Iwai {
29175f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29185f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29195f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
29205f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
29215f171baaSTakashi Iwai 	return 0;
29225f171baaSTakashi Iwai }
29235f171baaSTakashi Iwai 
29245f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
29255f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29265f171baaSTakashi Iwai {
29275f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29285f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29295f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29305f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29315f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
29325f171baaSTakashi Iwai 
29335f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
29345f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
29355f171baaSTakashi Iwai 	if (oldval == idx)
29365f171baaSTakashi Iwai 		return 0;
29375f171baaSTakashi Iwai 
29385f171baaSTakashi Iwai 	if (idx < out_jacks) {
29395f171baaSTakashi Iwai 		if (out_jacks > 1)
29405f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
29415f171baaSTakashi Iwai 		else
29425f171baaSTakashi Iwai 			val = PIN_HP;
29435f171baaSTakashi Iwai 	} else {
29445f171baaSTakashi Iwai 		idx -= out_jacks;
29455f171baaSTakashi Iwai 		if (in_jacks > 1) {
29465f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29475f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
29483f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
29493f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
29505f171baaSTakashi Iwai 		} else
295116c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
29525f171baaSTakashi Iwai 	}
29535f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2954963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
29558ba955ceSTakashi Iwai 
29565f171baaSTakashi Iwai 	return 1;
29575f171baaSTakashi Iwai }
29585f171baaSTakashi Iwai 
29595f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
29605f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
29615f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
29625f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
29635f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
29645f171baaSTakashi Iwai };
29655f171baaSTakashi Iwai 
29665f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
29675f171baaSTakashi Iwai {
29685f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
29695f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
29705f171baaSTakashi Iwai 
29715f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
29725f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
29735f171baaSTakashi Iwai 	if (!knew)
29745f171baaSTakashi Iwai 		return -ENOMEM;
29755f171baaSTakashi Iwai 	knew->private_value = pin;
29768ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
29775f171baaSTakashi Iwai 	return 0;
29785f171baaSTakashi Iwai }
2979352f7f91STakashi Iwai 
2980352f7f91STakashi Iwai /*
2981352f7f91STakashi Iwai  * Parse input paths
2982352f7f91STakashi Iwai  */
2983352f7f91STakashi Iwai 
2984352f7f91STakashi Iwai /* add the powersave loopback-list entry */
29850186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2986352f7f91STakashi Iwai {
2987352f7f91STakashi Iwai 	struct hda_amp_list *list;
2988352f7f91STakashi Iwai 
29890186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
29900186f4f4STakashi Iwai 	if (!list)
29910186f4f4STakashi Iwai 		return -ENOMEM;
2992352f7f91STakashi Iwai 	list->nid = mix;
2993352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2994352f7f91STakashi Iwai 	list->idx = idx;
29950186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
29960186f4f4STakashi Iwai 	return 0;
2997cb53c626STakashi Iwai }
2998cb53c626STakashi Iwai 
29992ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
30002ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
30012ded3e5bSTakashi Iwai  */
30022ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
30032ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
30042ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
30052ded3e5bSTakashi Iwai {
30062ded3e5bSTakashi Iwai 	int idx, num_conns;
30072ded3e5bSTakashi Iwai 	const hda_nid_t *list;
30082ded3e5bSTakashi Iwai 	hda_nid_t nid;
30092ded3e5bSTakashi Iwai 
30102ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
30112ded3e5bSTakashi Iwai 	if (idx < 0)
30122ded3e5bSTakashi Iwai 		return false;
30132ded3e5bSTakashi Iwai 
30142ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
30152ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
30162ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30172ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
30182ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30192ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
30202ded3e5bSTakashi Iwai 		return true;
30212ded3e5bSTakashi Iwai 
30222ded3e5bSTakashi Iwai 	/* check leaf node */
30232ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
30242ded3e5bSTakashi Iwai 	if (num_conns < idx)
30252ded3e5bSTakashi Iwai 		return false;
30262ded3e5bSTakashi Iwai 	nid = list[idx];
302743a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
302843a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
30292ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
303043a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
303143a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
30322ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
30332ded3e5bSTakashi Iwai 
30342ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
30352ded3e5bSTakashi Iwai }
30362ded3e5bSTakashi Iwai 
3037352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
3038196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
3039196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3040352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
30411da177e4SLinus Torvalds {
3042352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3043352f7f91STakashi Iwai 	struct nid_path *path;
30442ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
3045352f7f91STakashi Iwai 	int err, idx;
30461da177e4SLinus Torvalds 
30472ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
30482ded3e5bSTakashi Iwai 		return 0;
3049352f7f91STakashi Iwai 
30503ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3051352f7f91STakashi Iwai 	if (!path)
3052352f7f91STakashi Iwai 		return -EINVAL;
30534e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
3054196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3055352f7f91STakashi Iwai 
3056352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
30572ded3e5bSTakashi Iwai 	if (mix_val) {
30582ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3059d13bd412STakashi Iwai 		if (err < 0)
30601da177e4SLinus Torvalds 			return err;
30612ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
30621da177e4SLinus Torvalds 	}
30631da177e4SLinus Torvalds 
30642ded3e5bSTakashi Iwai 	if (mute_val) {
30652ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3066d13bd412STakashi Iwai 		if (err < 0)
30671da177e4SLinus Torvalds 			return err;
30682ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
30691da177e4SLinus Torvalds 	}
30701da177e4SLinus Torvalds 
3071352f7f91STakashi Iwai 	path->active = true;
3072e6feb5d0STakashi Iwai 	path->stream_enabled = true; /* no DAC/ADC involved */
30730186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
30740186f4f4STakashi Iwai 	if (err < 0)
30750186f4f4STakashi Iwai 		return err;
3076e4a395e7STakashi Iwai 
3077e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3078e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
3079e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3080e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
3081e4a395e7STakashi Iwai 		if (path) {
30824e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
3083e4a395e7STakashi Iwai 			path->active = true;
30846b275b14STakashi Iwai 			path->pin_fixed = true; /* static route */
3085e6feb5d0STakashi Iwai 			path->stream_enabled = true; /* no DAC/ADC involved */
3086e4a395e7STakashi Iwai 			spec->loopback_merge_path =
3087e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
3088e4a395e7STakashi Iwai 		}
3089e4a395e7STakashi Iwai 	}
3090e4a395e7STakashi Iwai 
3091352f7f91STakashi Iwai 	return 0;
30921da177e4SLinus Torvalds }
30931da177e4SLinus Torvalds 
3094352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
30951da177e4SLinus Torvalds {
3096352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3097352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
3098352f7f91STakashi Iwai }
3099352f7f91STakashi Iwai 
3100352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
3101352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
3102352f7f91STakashi Iwai {
3103352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3104352f7f91STakashi Iwai 	hda_nid_t nid;
3105352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
3106352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
31077639a06cSTakashi Iwai 	int nums = 0;
3108352f7f91STakashi Iwai 
31097639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
3110352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3111352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3112352f7f91STakashi Iwai 
3113352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3114352f7f91STakashi Iwai 			continue;
3115352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3116352f7f91STakashi Iwai 		if (++nums >= max_nums)
3117352f7f91STakashi Iwai 			break;
3118352f7f91STakashi Iwai 	}
3119352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
31200ffd534eSTakashi Iwai 
31210ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
31220ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
31230ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
31240ffd534eSTakashi Iwai 
3125352f7f91STakashi Iwai 	return nums;
3126352f7f91STakashi Iwai }
3127352f7f91STakashi Iwai 
3128352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3129352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3130352f7f91STakashi Iwai  */
3131352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3132352f7f91STakashi Iwai {
3133352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3134352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
31353a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3136352f7f91STakashi Iwai 	int i, n, nums;
3137352f7f91STakashi Iwai 
3138352f7f91STakashi Iwai 	nums = 0;
31393a65bcdcSTakashi Iwai 	ok_bits = 0;
3140352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3141352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
31423a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3143352f7f91STakashi Iwai 				break;
3144352f7f91STakashi Iwai 		}
31453a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
31463a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
31473a65bcdcSTakashi Iwai 			nums++;
31483a65bcdcSTakashi Iwai 		}
3149352f7f91STakashi Iwai 	}
3150352f7f91STakashi Iwai 
31513a65bcdcSTakashi Iwai 	if (!ok_bits) {
3152352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3153352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3154352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
31553a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3156352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3157352f7f91STakashi Iwai 					break;
3158352f7f91STakashi Iwai 				}
3159352f7f91STakashi Iwai 			}
3160352f7f91STakashi Iwai 		}
3161352f7f91STakashi Iwai 
31624e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3163352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3164352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
31653a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
31663a65bcdcSTakashi Iwai 		nums = 0;
31673a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
31683a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
31693a65bcdcSTakashi Iwai 				continue;
31703a65bcdcSTakashi Iwai 			if (n != nums) {
31713a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3172980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3173980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3174980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
31753a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
31763a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
3177a8f20fd2SHui Wang 					spec->input_paths[i][n] = 0;
31783a65bcdcSTakashi Iwai 				}
3179980428ceSTakashi Iwai 			}
31803a65bcdcSTakashi Iwai 			nums++;
31813a65bcdcSTakashi Iwai 		}
3182352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3183352f7f91STakashi Iwai 	}
3184352f7f91STakashi Iwai 
3185967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3186967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
31874e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3188352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3189352f7f91STakashi Iwai 	}
3190352f7f91STakashi Iwai 
3191352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3192352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3193352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3194352f7f91STakashi Iwai 
31951da177e4SLinus Torvalds 	return 0;
31961da177e4SLinus Torvalds }
31971da177e4SLinus Torvalds 
3198f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3199f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
32009dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
32019dba205bSTakashi Iwai 				const char *label, int anchor)
3202f3fc0b0bSTakashi Iwai {
3203f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3204f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3205f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3206f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3207f3fc0b0bSTakashi Iwai 	int c;
3208f3fc0b0bSTakashi Iwai 
3209f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3210f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3211f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3212f3fc0b0bSTakashi Iwai 
3213f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3214f3fc0b0bSTakashi Iwai 			continue;
3215f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3216f3fc0b0bSTakashi Iwai 		if (!path)
3217f3fc0b0bSTakashi Iwai 			continue;
32184e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3219f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3220f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3221f3fc0b0bSTakashi Iwai 
3222f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3223967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3224967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3225f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
32266194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3227f3fc0b0bSTakashi Iwai 			imux_added = true;
3228f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3229f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3230f3fc0b0bSTakashi Iwai 		}
3231f3fc0b0bSTakashi Iwai 	}
3232f3fc0b0bSTakashi Iwai 
3233f3fc0b0bSTakashi Iwai 	return 0;
3234f3fc0b0bSTakashi Iwai }
3235f3fc0b0bSTakashi Iwai 
32361da177e4SLinus Torvalds /*
3237352f7f91STakashi Iwai  * create playback/capture controls for input pins
32381da177e4SLinus Torvalds  */
32399dba205bSTakashi Iwai 
3240c970042cSTakashi Iwai /* fill the label for each input at first */
3241c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3242c970042cSTakashi Iwai {
3243c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3244c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3245c970042cSTakashi Iwai 	int i;
3246c970042cSTakashi Iwai 
3247c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3248c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3249c970042cSTakashi Iwai 		const char *label;
3250c970042cSTakashi Iwai 		int j, idx;
3251c970042cSTakashi Iwai 
3252c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3253c970042cSTakashi Iwai 			continue;
3254c970042cSTakashi Iwai 
3255c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3256c970042cSTakashi Iwai 		idx = 0;
32578e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3258c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3259c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3260c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3261c970042cSTakashi Iwai 				break;
3262c970042cSTakashi Iwai 			}
3263c970042cSTakashi Iwai 		}
3264c970042cSTakashi Iwai 
3265c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3266c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3267c970042cSTakashi Iwai 	}
3268c970042cSTakashi Iwai 
3269c970042cSTakashi Iwai 	return 0;
3270c970042cSTakashi Iwai }
3271c970042cSTakashi Iwai 
32729dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
32739dba205bSTakashi Iwai 
3274352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3275a7da6ce5STakashi Iwai {
3276352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3277352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3278352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3279352f7f91STakashi Iwai 	int num_adcs;
3280c970042cSTakashi Iwai 	int i, err;
32812c12c30dSTakashi Iwai 	unsigned int val;
3282a7da6ce5STakashi Iwai 
3283352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3284352f7f91STakashi Iwai 	if (num_adcs < 0)
3285352f7f91STakashi Iwai 		return 0;
3286352f7f91STakashi Iwai 
3287c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3288c970042cSTakashi Iwai 	if (err < 0)
3289c970042cSTakashi Iwai 		return err;
3290c970042cSTakashi Iwai 
3291352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3292352f7f91STakashi Iwai 		hda_nid_t pin;
3293352f7f91STakashi Iwai 
3294352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3295352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3296352f7f91STakashi Iwai 			continue;
3297352f7f91STakashi Iwai 
32982c12c30dSTakashi Iwai 		val = PIN_IN;
32992c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
33002c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
33013e1b0c4aSTakashi Iwai 		if (pin != spec->hp_mic_pin &&
33023e1b0c4aSTakashi Iwai 		    !snd_hda_codec_get_pin_target(codec, pin))
33032c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
33042c12c30dSTakashi Iwai 
3305352f7f91STakashi Iwai 		if (mixer) {
3306352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3307196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3308c970042cSTakashi Iwai 						       spec->input_labels[i],
3309c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3310c970042cSTakashi Iwai 						       mixer);
3311a7da6ce5STakashi Iwai 				if (err < 0)
3312a7da6ce5STakashi Iwai 					return err;
3313a7da6ce5STakashi Iwai 			}
3314352f7f91STakashi Iwai 		}
3315352f7f91STakashi Iwai 
3316c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3317c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3318f3fc0b0bSTakashi Iwai 		if (err < 0)
3319f3fc0b0bSTakashi Iwai 			return err;
332029476558STakashi Iwai 
3321f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
332229476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
332329476558STakashi Iwai 			if (err < 0)
332429476558STakashi Iwai 				return err;
332529476558STakashi Iwai 		}
3326352f7f91STakashi Iwai 	}
3327f3fc0b0bSTakashi Iwai 
3328f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
332974f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
33309dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3331f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3332f3fc0b0bSTakashi Iwai 		if (err < 0)
3333f3fc0b0bSTakashi Iwai 			return err;
333482d04e10STakashi Iwai 		else
333582d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3336352f7f91STakashi Iwai 	}
3337352f7f91STakashi Iwai 
3338a7da6ce5STakashi Iwai 	return 0;
3339a7da6ce5STakashi Iwai }
3340a7da6ce5STakashi Iwai 
33411da177e4SLinus Torvalds 
3342352f7f91STakashi Iwai /*
3343352f7f91STakashi Iwai  * input source mux
3344352f7f91STakashi Iwai  */
3345352f7f91STakashi Iwai 
3346c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3347c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3348352f7f91STakashi Iwai {
3349352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3350b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3351b56fa1edSDavid Henningsson 		snd_BUG();
3352b56fa1edSDavid Henningsson 		return NULL;
3353b56fa1edSDavid Henningsson 	}
3354352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3355352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3356d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3357b56fa1edSDavid Henningsson 		snd_BUG();
3358b56fa1edSDavid Henningsson 		return NULL;
3359b56fa1edSDavid Henningsson 	}
3360c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
336197ec558aSTakashi Iwai }
3362352f7f91STakashi Iwai 
3363352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3364352f7f91STakashi Iwai 		      unsigned int idx);
3365352f7f91STakashi Iwai 
3366352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3367352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3368352f7f91STakashi Iwai {
3369352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3370352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3371352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3372352f7f91STakashi Iwai }
3373352f7f91STakashi Iwai 
3374352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3375352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3376352f7f91STakashi Iwai {
3377352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3378352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
33792a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
33802a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3381352f7f91STakashi Iwai 
3382352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
33831da177e4SLinus Torvalds 	return 0;
33841da177e4SLinus Torvalds }
33851da177e4SLinus Torvalds 
3386352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3387352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
33881da177e4SLinus Torvalds {
3389352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
33902a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3391352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3392352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3393352f7f91STakashi Iwai }
3394352f7f91STakashi Iwai 
3395352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
33961da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3397352f7f91STakashi Iwai 	.name = "Input Source",
3398352f7f91STakashi Iwai 	.info = mux_enum_info,
3399352f7f91STakashi Iwai 	.get = mux_enum_get,
3400352f7f91STakashi Iwai 	.put = mux_enum_put,
34011da177e4SLinus Torvalds };
3402071c73adSTakashi Iwai 
340347d46abbSTakashi Iwai /*
340447d46abbSTakashi Iwai  * capture volume and capture switch ctls
340547d46abbSTakashi Iwai  */
340647d46abbSTakashi Iwai 
3407352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3408352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3409071c73adSTakashi Iwai 
341047d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3411352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3412352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3413352f7f91STakashi Iwai 			  put_call_t func, int type)
3414352f7f91STakashi Iwai {
3415352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3416352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3417352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3418352f7f91STakashi Iwai 	struct nid_path *path;
3419352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3420071c73adSTakashi Iwai 
3421352f7f91STakashi Iwai 	imux = &spec->input_mux;
3422a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3423352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
3424352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3425c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3426c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3427352f7f91STakashi Iwai 			continue;
3428352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3429352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3430352f7f91STakashi Iwai 		if (err < 0)
3431a551d914STakashi Iwai 			break;
3432352f7f91STakashi Iwai 	}
3433352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3434352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
34357fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3436352f7f91STakashi Iwai 	return err;
3437352f7f91STakashi Iwai }
3438352f7f91STakashi Iwai 
3439352f7f91STakashi Iwai /* capture volume ctl callbacks */
3440352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3441352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3442352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3443352f7f91STakashi Iwai 
3444352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3445352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3446352f7f91STakashi Iwai {
3447352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3448352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3449352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3450352f7f91STakashi Iwai }
3451352f7f91STakashi Iwai 
3452352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3453352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3454352f7f91STakashi Iwai 	.name = "Capture Volume",
3455352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3456352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3457352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3458352f7f91STakashi Iwai 	.info = cap_vol_info,
3459352f7f91STakashi Iwai 	.get = cap_vol_get,
3460352f7f91STakashi Iwai 	.put = cap_vol_put,
3461352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3462352f7f91STakashi Iwai };
3463352f7f91STakashi Iwai 
3464352f7f91STakashi Iwai /* capture switch ctl callbacks */
3465352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3466352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3467352f7f91STakashi Iwai 
3468352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3469352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3470352f7f91STakashi Iwai {
3471a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3472352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3473352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3474352f7f91STakashi Iwai }
3475352f7f91STakashi Iwai 
3476352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3477352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3478352f7f91STakashi Iwai 	.name = "Capture Switch",
3479352f7f91STakashi Iwai 	.info = cap_sw_info,
3480352f7f91STakashi Iwai 	.get = cap_sw_get,
3481352f7f91STakashi Iwai 	.put = cap_sw_put,
3482352f7f91STakashi Iwai };
3483352f7f91STakashi Iwai 
3484352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3485352f7f91STakashi Iwai {
3486352f7f91STakashi Iwai 	hda_nid_t nid;
3487352f7f91STakashi Iwai 	int i, depth;
3488352f7f91STakashi Iwai 
3489352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3490352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3491352f7f91STakashi Iwai 		if (depth >= path->depth)
3492352f7f91STakashi Iwai 			return -EINVAL;
3493352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3494352f7f91STakashi Iwai 		nid = path->path[i];
3495352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3496352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3497352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3498352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3499352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3500352f7f91STakashi Iwai 				int idx = path->idx[i];
3501352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3502352f7f91STakashi Iwai 					idx = 0;
3503352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3504352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3505352f7f91STakashi Iwai 			}
3506352f7f91STakashi Iwai 		}
3507352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3508352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3509352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3510352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3511352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3512352f7f91STakashi Iwai 				int idx = path->idx[i];
3513352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3514352f7f91STakashi Iwai 					idx = 0;
3515352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3516352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3517352f7f91STakashi Iwai 			}
3518352f7f91STakashi Iwai 		}
3519352f7f91STakashi Iwai 	}
3520352f7f91STakashi Iwai 	return 0;
3521352f7f91STakashi Iwai }
3522352f7f91STakashi Iwai 
3523352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3524352f7f91STakashi Iwai {
3525352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3526352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3527352f7f91STakashi Iwai 	unsigned int val;
3528352f7f91STakashi Iwai 	int i;
3529352f7f91STakashi Iwai 
3530352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3531352f7f91STakashi Iwai 		return false;
3532352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3533352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3534352f7f91STakashi Iwai 			continue;
3535352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3536352f7f91STakashi Iwai 			return false;
3537352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3538352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3539352f7f91STakashi Iwai 	}
3540352f7f91STakashi Iwai 	return false;
3541352f7f91STakashi Iwai }
3542352f7f91STakashi Iwai 
3543a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3544a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3545a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3546a35bd1e3STakashi Iwai {
3547a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3548a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3549a35bd1e3STakashi Iwai 	int ret;
3550a35bd1e3STakashi Iwai 
3551a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3552a35bd1e3STakashi Iwai 	if (ret < 0)
3553a35bd1e3STakashi Iwai 		return ret;
3554a35bd1e3STakashi Iwai 
3555a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
35567fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3557a35bd1e3STakashi Iwai 
3558a35bd1e3STakashi Iwai 	return ret;
3559a35bd1e3STakashi Iwai }
3560a35bd1e3STakashi Iwai 
3561352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3562352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3563352f7f91STakashi Iwai 			      bool inv_dmic)
3564352f7f91STakashi Iwai {
3565352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3566975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3567352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3568352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3569352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3570a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3571352f7f91STakashi Iwai 
3572352f7f91STakashi Iwai 	if (!ctl)
3573352f7f91STakashi Iwai 		return 0;
3574352f7f91STakashi Iwai 
3575352f7f91STakashi Iwai 	if (label)
3576352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3577352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3578352f7f91STakashi Iwai 	else
3579352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3580352f7f91STakashi Iwai 			 "Capture %s", sfx);
3581a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3582352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3583a35bd1e3STakashi Iwai 	if (!knew)
3584a35bd1e3STakashi Iwai 		return -ENOMEM;
3585a90229e0STakashi Iwai 	if (is_switch)
3586a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3587a35bd1e3STakashi Iwai 	if (!inv_dmic)
3588a35bd1e3STakashi Iwai 		return 0;
3589352f7f91STakashi Iwai 
3590352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3591352f7f91STakashi Iwai 	if (label)
3592352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3593352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3594352f7f91STakashi Iwai 	else
3595352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3596352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3597a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3598352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3599a35bd1e3STakashi Iwai 	if (!knew)
3600a35bd1e3STakashi Iwai 		return -ENOMEM;
3601a90229e0STakashi Iwai 	if (is_switch)
3602a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3603a35bd1e3STakashi Iwai 	return 0;
3604352f7f91STakashi Iwai }
3605352f7f91STakashi Iwai 
3606352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3607352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3608352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3609352f7f91STakashi Iwai 				     bool inv_dmic)
3610352f7f91STakashi Iwai {
3611352f7f91STakashi Iwai 	int err;
3612352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3613352f7f91STakashi Iwai 	if (err < 0)
3614352f7f91STakashi Iwai 		return err;
3615352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3616071c73adSTakashi Iwai 	if (err < 0)
3617071c73adSTakashi Iwai 		return err;
3618071c73adSTakashi Iwai 	return 0;
36191da177e4SLinus Torvalds }
3620071c73adSTakashi Iwai 
3621352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3622352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3623352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3624352f7f91STakashi Iwai {
3625352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3626352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3627352f7f91STakashi Iwai 
3628352f7f91STakashi Iwai 	if (vol_ctl) {
362912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3630352f7f91STakashi Iwai 		if (!knew)
3631352f7f91STakashi Iwai 			return -ENOMEM;
3632352f7f91STakashi Iwai 		knew->index = idx;
3633352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3634352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3635352f7f91STakashi Iwai 	}
3636352f7f91STakashi Iwai 	if (sw_ctl) {
363712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3638352f7f91STakashi Iwai 		if (!knew)
3639352f7f91STakashi Iwai 			return -ENOMEM;
3640352f7f91STakashi Iwai 		knew->index = idx;
3641352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3642352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3643352f7f91STakashi Iwai 	}
3644352f7f91STakashi Iwai 	return 0;
3645352f7f91STakashi Iwai }
3646352f7f91STakashi Iwai 
3647352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3648352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3649352f7f91STakashi Iwai {
3650352f7f91STakashi Iwai 	struct nid_path *path;
3651352f7f91STakashi Iwai 	unsigned int ctl;
3652352f7f91STakashi Iwai 	int i;
3653352f7f91STakashi Iwai 
3654c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3655352f7f91STakashi Iwai 	if (!path)
3656352f7f91STakashi Iwai 		return 0;
3657352f7f91STakashi Iwai 	ctl = path->ctls[type];
3658352f7f91STakashi Iwai 	if (!ctl)
3659352f7f91STakashi Iwai 		return 0;
3660352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3661c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3662352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3663352f7f91STakashi Iwai 			return 0;
3664352f7f91STakashi Iwai 	}
3665352f7f91STakashi Iwai 	return ctl;
3666352f7f91STakashi Iwai }
3667352f7f91STakashi Iwai 
3668352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3669352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3670352f7f91STakashi Iwai {
3671352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3672352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3673c970042cSTakashi Iwai 	int i, err, type;
3674352f7f91STakashi Iwai 
3675352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3676352f7f91STakashi Iwai 		bool inv_dmic;
3677c970042cSTakashi Iwai 		int idx;
36789dba205bSTakashi Iwai 
3679c970042cSTakashi Iwai 		idx = imux->items[i].index;
3680c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
36819dba205bSTakashi Iwai 			continue;
3682352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3683352f7f91STakashi Iwai 
3684352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3685c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3686c970042cSTakashi Iwai 						 spec->input_labels[idx],
3687c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3688c970042cSTakashi Iwai 						 type,
3689352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3690352f7f91STakashi Iwai 						 inv_dmic);
3691d13bd412STakashi Iwai 			if (err < 0)
3692071c73adSTakashi Iwai 				return err;
3693352f7f91STakashi Iwai 		}
3694352f7f91STakashi Iwai 	}
3695071c73adSTakashi Iwai 	return 0;
3696352f7f91STakashi Iwai }
3697071c73adSTakashi Iwai 
3698352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3699352f7f91STakashi Iwai {
3700352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3701352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3702352f7f91STakashi Iwai 	int i, n, nums, err;
3703352f7f91STakashi Iwai 
3704352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3705352f7f91STakashi Iwai 		nums = 1;
3706352f7f91STakashi Iwai 	else
3707352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3708352f7f91STakashi Iwai 
3709352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3710352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3711624d914dSTakashi Iwai 		const char *name;
3712624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3713624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3714352f7f91STakashi Iwai 		if (!knew)
3715352f7f91STakashi Iwai 			return -ENOMEM;
3716352f7f91STakashi Iwai 		knew->count = nums;
3717352f7f91STakashi Iwai 	}
3718352f7f91STakashi Iwai 
3719352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3720352f7f91STakashi Iwai 		bool multi = false;
372199a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3722352f7f91STakashi Iwai 		bool inv_dmic = false;
3723352f7f91STakashi Iwai 		int vol, sw;
3724352f7f91STakashi Iwai 
3725352f7f91STakashi Iwai 		vol = sw = 0;
3726352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3727352f7f91STakashi Iwai 			struct nid_path *path;
3728c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3729352f7f91STakashi Iwai 			if (!path)
3730352f7f91STakashi Iwai 				continue;
3731352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3732352f7f91STakashi Iwai 			if (!vol)
3733352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
373499a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3735352f7f91STakashi Iwai 				multi = true;
373699a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
373799a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
373899a5592dSDavid Henningsson 					multi_cap_vol = true;
373999a5592dSDavid Henningsson 			}
3740352f7f91STakashi Iwai 			if (!sw)
3741352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
374299a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3743352f7f91STakashi Iwai 				multi = true;
374499a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
374599a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
374699a5592dSDavid Henningsson 					multi_cap_vol = true;
374799a5592dSDavid Henningsson 			}
3748352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3749352f7f91STakashi Iwai 				inv_dmic = true;
3750352f7f91STakashi Iwai 		}
3751352f7f91STakashi Iwai 
3752352f7f91STakashi Iwai 		if (!multi)
3753352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3754352f7f91STakashi Iwai 							inv_dmic);
3755ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3756352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3757352f7f91STakashi Iwai 		else
3758352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3759d13bd412STakashi Iwai 		if (err < 0)
3760071c73adSTakashi Iwai 			return err;
3761071c73adSTakashi Iwai 	}
3762071c73adSTakashi Iwai 
37631da177e4SLinus Torvalds 	return 0;
37641da177e4SLinus Torvalds }
37651da177e4SLinus Torvalds 
3766352f7f91STakashi Iwai /*
3767352f7f91STakashi Iwai  * add mic boosts if needed
3768352f7f91STakashi Iwai  */
37696f7c83afSTakashi Iwai 
37706f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
37716f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
37726f7c83afSTakashi Iwai 			    int dir, int idx)
37736f7c83afSTakashi Iwai {
37746f7c83afSTakashi Iwai 	unsigned int step;
37756f7c83afSTakashi Iwai 
37766f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
37776f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
37786f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
37796f7c83afSTakashi Iwai 		return false;
37806f7c83afSTakashi Iwai 
37816f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
37826f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
37836f7c83afSTakashi Iwai 	if (step < 0x20)
37846f7c83afSTakashi Iwai 		return false;
37856f7c83afSTakashi Iwai 	return true;
37866f7c83afSTakashi Iwai }
37876f7c83afSTakashi Iwai 
37886f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
37896f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
37906f7c83afSTakashi Iwai 				       struct nid_path *path)
37916f7c83afSTakashi Iwai {
37926f7c83afSTakashi Iwai 	unsigned int val = 0;
37936f7c83afSTakashi Iwai 	hda_nid_t nid;
37946f7c83afSTakashi Iwai 	int depth;
37956f7c83afSTakashi Iwai 
37966f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
37976f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
37986f7c83afSTakashi Iwai 			break;
37996f7c83afSTakashi Iwai 		nid = path->path[depth];
38006f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
38016f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
38026f7c83afSTakashi Iwai 			break;
38036f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
38046f7c83afSTakashi Iwai 					   path->idx[depth])) {
38056f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
38066f7c83afSTakashi Iwai 						  HDA_INPUT);
38076f7c83afSTakashi Iwai 			break;
38086f7c83afSTakashi Iwai 		}
38096f7c83afSTakashi Iwai 	}
38106f7c83afSTakashi Iwai 
38116f7c83afSTakashi Iwai 	return val;
38126f7c83afSTakashi Iwai }
38136f7c83afSTakashi Iwai 
3814352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3815352f7f91STakashi Iwai {
3816352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3817352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
38186f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3819a35bd1e3STakashi Iwai 	int i;
3820352f7f91STakashi Iwai 
38216f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
38226f7c83afSTakashi Iwai 		return 0;
38236f7c83afSTakashi Iwai 
38246f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3825352f7f91STakashi Iwai 		struct nid_path *path;
3826352f7f91STakashi Iwai 		unsigned int val;
38276f7c83afSTakashi Iwai 		int idx;
3828975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3829352f7f91STakashi Iwai 
38306f7c83afSTakashi Iwai 		idx = imux->items[i].index;
38316f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
383202aba550SDavid Henningsson 			continue;
383302aba550SDavid Henningsson 
38346f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
38351799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
38366f7c83afSTakashi Iwai 			continue;
38376f7c83afSTakashi Iwai 
38386f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
38396f7c83afSTakashi Iwai 		if (!path)
38406f7c83afSTakashi Iwai 			continue;
38416f7c83afSTakashi Iwai 
38426f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
38436f7c83afSTakashi Iwai 		if (!val)
38446f7c83afSTakashi Iwai 			continue;
38456f7c83afSTakashi Iwai 
38466f7c83afSTakashi Iwai 		/* create a boost control */
3847352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
38486f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3849a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3850a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3851a35bd1e3STakashi Iwai 			return -ENOMEM;
3852352f7f91STakashi Iwai 
3853352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3854352f7f91STakashi Iwai 	}
3855352f7f91STakashi Iwai 	return 0;
3856352f7f91STakashi Iwai }
3857352f7f91STakashi Iwai 
3858352f7f91STakashi Iwai /*
3859352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3860352f7f91STakashi Iwai  */
3861352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3862352f7f91STakashi Iwai {
3863352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
38640c8c0f56STakashi Iwai 	struct nid_path *path;
3865352f7f91STakashi Iwai 	int i, nums;
38662c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3867352f7f91STakashi Iwai 
3868352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3869352f7f91STakashi Iwai 	nums = 0;
3870352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
38712c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3872352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3873352f7f91STakashi Iwai 		if (!dig_nid)
3874352f7f91STakashi Iwai 			continue;
38753ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
38760c8c0f56STakashi Iwai 		if (!path)
3877352f7f91STakashi Iwai 			continue;
38784e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
3879e1284af7STakashi Iwai 		path->active = true;
38806b275b14STakashi Iwai 		path->pin_fixed = true; /* no jack detection */
3881196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
38822c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3883352f7f91STakashi Iwai 		if (!nums) {
3884352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3885352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3886352f7f91STakashi Iwai 		} else {
3887352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3888352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3889352f7f91STakashi Iwai 				break;
3890352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3891352f7f91STakashi Iwai 		}
3892352f7f91STakashi Iwai 		nums++;
3893352f7f91STakashi Iwai 	}
3894352f7f91STakashi Iwai 
3895352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
38962c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
38977639a06cSTakashi Iwai 		for_each_hda_codec_node(dig_nid, codec) {
3898352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3899352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3900352f7f91STakashi Iwai 				continue;
3901352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3902352f7f91STakashi Iwai 				continue;
39032c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3904352f7f91STakashi Iwai 			if (path) {
39054e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
3906352f7f91STakashi Iwai 				path->active = true;
39076b275b14STakashi Iwai 				path->pin_fixed = true; /* no jack */
3908352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
39092430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
39102c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3911352f7f91STakashi Iwai 				break;
3912352f7f91STakashi Iwai 			}
3913352f7f91STakashi Iwai 		}
3914352f7f91STakashi Iwai 	}
3915352f7f91STakashi Iwai }
3916352f7f91STakashi Iwai 
39171da177e4SLinus Torvalds 
39181da177e4SLinus Torvalds /*
3919352f7f91STakashi Iwai  * input MUX handling
39201da177e4SLinus Torvalds  */
39211da177e4SLinus Torvalds 
3922352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3923352f7f91STakashi Iwai 
3924352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3925352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3926352f7f91STakashi Iwai 		      unsigned int idx)
3927352f7f91STakashi Iwai {
3928352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3929352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
393055196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3931352f7f91STakashi Iwai 
3932352f7f91STakashi Iwai 	imux = &spec->input_mux;
3933352f7f91STakashi Iwai 	if (!imux->num_items)
39341da177e4SLinus Torvalds 		return 0;
39351da177e4SLinus Torvalds 
3936352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3937352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3938352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3939352f7f91STakashi Iwai 		return 0;
3940352f7f91STakashi Iwai 
394155196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
394255196fffSTakashi Iwai 	if (!old_path)
3943352f7f91STakashi Iwai 		return 0;
394455196fffSTakashi Iwai 	if (old_path->active)
394555196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3946352f7f91STakashi Iwai 
3947352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3948352f7f91STakashi Iwai 
3949967303daSTakashi Iwai 	if (spec->hp_mic)
3950967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3951352f7f91STakashi Iwai 
3952352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3953352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3954352f7f91STakashi Iwai 
3955c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3956352f7f91STakashi Iwai 	if (!path)
3957352f7f91STakashi Iwai 		return 0;
3958352f7f91STakashi Iwai 	if (path->active)
3959352f7f91STakashi Iwai 		return 0;
3960352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3961352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
39627fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
396355196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
39641da177e4SLinus Torvalds 	return 1;
39651da177e4SLinus Torvalds }
39661da177e4SLinus Torvalds 
3967e6feb5d0STakashi Iwai /* power up/down widgets in the all paths that match with the given NID
3968e6feb5d0STakashi Iwai  * as terminals (either start- or endpoint)
3969e6feb5d0STakashi Iwai  *
3970e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
3971e6feb5d0STakashi Iwai  */
3972e6feb5d0STakashi Iwai static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
3973e6feb5d0STakashi Iwai 				int pin_state, int stream_state)
3974e6feb5d0STakashi Iwai {
3975e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3976e6feb5d0STakashi Iwai 	hda_nid_t last, changed = 0;
3977e6feb5d0STakashi Iwai 	struct nid_path *path;
3978e6feb5d0STakashi Iwai 	int n;
3979e6feb5d0STakashi Iwai 
3980e6feb5d0STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
3981e6feb5d0STakashi Iwai 		path = snd_array_elem(&spec->paths, n);
398281e43960SBob Copeland 		if (!path->depth)
398381e43960SBob Copeland 			continue;
3984e6feb5d0STakashi Iwai 		if (path->path[0] == nid ||
3985e6feb5d0STakashi Iwai 		    path->path[path->depth - 1] == nid) {
3986e6feb5d0STakashi Iwai 			bool pin_old = path->pin_enabled;
3987e6feb5d0STakashi Iwai 			bool stream_old = path->stream_enabled;
3988e6feb5d0STakashi Iwai 
3989e6feb5d0STakashi Iwai 			if (pin_state >= 0)
3990e6feb5d0STakashi Iwai 				path->pin_enabled = pin_state;
3991e6feb5d0STakashi Iwai 			if (stream_state >= 0)
3992e6feb5d0STakashi Iwai 				path->stream_enabled = stream_state;
39936b275b14STakashi Iwai 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
39946b275b14STakashi Iwai 			    || path->stream_enabled != stream_old) {
3995e6feb5d0STakashi Iwai 				last = path_power_update(codec, path, true);
3996e6feb5d0STakashi Iwai 				if (last)
3997e6feb5d0STakashi Iwai 					changed = last;
3998e6feb5d0STakashi Iwai 			}
3999e6feb5d0STakashi Iwai 		}
4000e6feb5d0STakashi Iwai 	}
4001e6feb5d0STakashi Iwai 	return changed;
4002e6feb5d0STakashi Iwai }
4003e6feb5d0STakashi Iwai 
4004d5ac0100STakashi Iwai /* check the jack status for power control */
4005d5ac0100STakashi Iwai static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4006d5ac0100STakashi Iwai {
4007d5ac0100STakashi Iwai 	if (!is_jack_detectable(codec, pin))
4008d5ac0100STakashi Iwai 		return true;
4009d5ac0100STakashi Iwai 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4010d5ac0100STakashi Iwai }
4011d5ac0100STakashi Iwai 
4012e6feb5d0STakashi Iwai /* power up/down the paths of the given pin according to the jack state;
4013e6feb5d0STakashi Iwai  * power = 0/1 : only power up/down if it matches with the jack state,
4014e6feb5d0STakashi Iwai  *       < 0   : force power up/down to follow the jack sate
4015e6feb5d0STakashi Iwai  *
4016e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4017e6feb5d0STakashi Iwai  */
4018e6feb5d0STakashi Iwai static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4019e6feb5d0STakashi Iwai 				    int power)
4020e6feb5d0STakashi Iwai {
4021e6feb5d0STakashi Iwai 	bool on;
4022e6feb5d0STakashi Iwai 
4023967b1307STakashi Iwai 	if (!codec->power_save_node)
4024e6feb5d0STakashi Iwai 		return 0;
4025e6feb5d0STakashi Iwai 
4026d5ac0100STakashi Iwai 	on = detect_pin_state(codec, pin);
4027d5ac0100STakashi Iwai 
4028e6feb5d0STakashi Iwai 	if (power >= 0 && on != power)
4029e6feb5d0STakashi Iwai 		return 0;
4030e6feb5d0STakashi Iwai 	return set_path_power(codec, pin, on, -1);
4031e6feb5d0STakashi Iwai }
4032e6feb5d0STakashi Iwai 
4033e6feb5d0STakashi Iwai static void pin_power_callback(struct hda_codec *codec,
4034e6feb5d0STakashi Iwai 			       struct hda_jack_callback *jack,
4035e6feb5d0STakashi Iwai 			       bool on)
4036e6feb5d0STakashi Iwai {
40372ebab40eSTakashi Iwai 	if (jack && jack->nid)
4038e6feb5d0STakashi Iwai 		sync_power_state_change(codec,
40392ebab40eSTakashi Iwai 					set_pin_power_jack(codec, jack->nid, on));
4040e6feb5d0STakashi Iwai }
4041e6feb5d0STakashi Iwai 
4042e6feb5d0STakashi Iwai /* callback only doing power up -- called at first */
4043e6feb5d0STakashi Iwai static void pin_power_up_callback(struct hda_codec *codec,
4044e6feb5d0STakashi Iwai 				  struct hda_jack_callback *jack)
4045e6feb5d0STakashi Iwai {
4046e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, true);
4047e6feb5d0STakashi Iwai }
4048e6feb5d0STakashi Iwai 
4049e6feb5d0STakashi Iwai /* callback only doing power down -- called at last */
4050e6feb5d0STakashi Iwai static void pin_power_down_callback(struct hda_codec *codec,
4051e6feb5d0STakashi Iwai 				    struct hda_jack_callback *jack)
4052e6feb5d0STakashi Iwai {
4053e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, false);
4054e6feb5d0STakashi Iwai }
4055e6feb5d0STakashi Iwai 
4056e6feb5d0STakashi Iwai /* set up the power up/down callbacks */
4057e6feb5d0STakashi Iwai static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4058e6feb5d0STakashi Iwai 			       const hda_nid_t *pins, bool on)
4059e6feb5d0STakashi Iwai {
4060e6feb5d0STakashi Iwai 	int i;
4061e6feb5d0STakashi Iwai 	hda_jack_callback_fn cb =
4062e6feb5d0STakashi Iwai 		on ? pin_power_up_callback : pin_power_down_callback;
4063e6feb5d0STakashi Iwai 
4064e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++) {
4065e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4066e6feb5d0STakashi Iwai 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4067e6feb5d0STakashi Iwai 		else
4068e6feb5d0STakashi Iwai 			set_path_power(codec, pins[i], true, -1);
4069e6feb5d0STakashi Iwai 	}
4070e6feb5d0STakashi Iwai }
4071e6feb5d0STakashi Iwai 
4072e6feb5d0STakashi Iwai /* enabled power callback to each available I/O pin with jack detections;
4073e6feb5d0STakashi Iwai  * the digital I/O pins are excluded because of the unreliable detectsion
4074e6feb5d0STakashi Iwai  */
4075e6feb5d0STakashi Iwai static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4076e6feb5d0STakashi Iwai {
4077e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4078e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4079e6feb5d0STakashi Iwai 	int i;
4080e6feb5d0STakashi Iwai 
4081967b1307STakashi Iwai 	if (!codec->power_save_node)
4082e6feb5d0STakashi Iwai 		return;
4083e6feb5d0STakashi Iwai 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4084e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4085e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4086e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4087e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4088e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4089e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4090e6feb5d0STakashi Iwai }
4091e6feb5d0STakashi Iwai 
4092e6feb5d0STakashi Iwai /* sync path power up/down with the jack states of given pins */
4093e6feb5d0STakashi Iwai static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4094e6feb5d0STakashi Iwai 				const hda_nid_t *pins)
4095e6feb5d0STakashi Iwai {
4096e6feb5d0STakashi Iwai 	int i;
4097e6feb5d0STakashi Iwai 
4098e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++)
4099e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4100e6feb5d0STakashi Iwai 			set_pin_power_jack(codec, pins[i], -1);
4101e6feb5d0STakashi Iwai }
4102e6feb5d0STakashi Iwai 
4103e6feb5d0STakashi Iwai /* sync path power up/down with pins; called at init and resume */
4104e6feb5d0STakashi Iwai static void sync_all_pin_power_ctls(struct hda_codec *codec)
4105e6feb5d0STakashi Iwai {
4106e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4107e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4108e6feb5d0STakashi Iwai 	int i;
4109e6feb5d0STakashi Iwai 
4110967b1307STakashi Iwai 	if (!codec->power_save_node)
4111e6feb5d0STakashi Iwai 		return;
4112e6feb5d0STakashi Iwai 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4113e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4114e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4115e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4116e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4117e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4118e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4119e6feb5d0STakashi Iwai }
41201da177e4SLinus Torvalds 
41215ccf835cSTakashi Iwai /* add fake paths if not present yet */
41225ccf835cSTakashi Iwai static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
41235ccf835cSTakashi Iwai 			   int num_pins, const hda_nid_t *pins)
41245ccf835cSTakashi Iwai {
41255ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41265ccf835cSTakashi Iwai 	struct nid_path *path;
41275ccf835cSTakashi Iwai 	int i;
41285ccf835cSTakashi Iwai 
41295ccf835cSTakashi Iwai 	for (i = 0; i < num_pins; i++) {
41305ccf835cSTakashi Iwai 		if (!pins[i])
41315ccf835cSTakashi Iwai 			break;
41325ccf835cSTakashi Iwai 		if (get_nid_path(codec, nid, pins[i], 0))
41335ccf835cSTakashi Iwai 			continue;
41345ccf835cSTakashi Iwai 		path = snd_array_new(&spec->paths);
41355ccf835cSTakashi Iwai 		if (!path)
41365ccf835cSTakashi Iwai 			return -ENOMEM;
41375ccf835cSTakashi Iwai 		memset(path, 0, sizeof(*path));
41385ccf835cSTakashi Iwai 		path->depth = 2;
41395ccf835cSTakashi Iwai 		path->path[0] = nid;
41405ccf835cSTakashi Iwai 		path->path[1] = pins[i];
41415ccf835cSTakashi Iwai 		path->active = true;
41425ccf835cSTakashi Iwai 	}
41435ccf835cSTakashi Iwai 	return 0;
41445ccf835cSTakashi Iwai }
41455ccf835cSTakashi Iwai 
41465ccf835cSTakashi Iwai /* create fake paths to all outputs from beep */
41475ccf835cSTakashi Iwai static int add_fake_beep_paths(struct hda_codec *codec)
41485ccf835cSTakashi Iwai {
41495ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41505ccf835cSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
41515ccf835cSTakashi Iwai 	hda_nid_t nid = spec->beep_nid;
41525ccf835cSTakashi Iwai 	int err;
41535ccf835cSTakashi Iwai 
4154967b1307STakashi Iwai 	if (!codec->power_save_node || !nid)
41555ccf835cSTakashi Iwai 		return 0;
41565ccf835cSTakashi Iwai 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
41575ccf835cSTakashi Iwai 	if (err < 0)
41585ccf835cSTakashi Iwai 		return err;
41595ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
41605ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
41615ccf835cSTakashi Iwai 		if (err < 0)
41625ccf835cSTakashi Iwai 			return err;
41635ccf835cSTakashi Iwai 	}
41645ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
41655ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
41665ccf835cSTakashi Iwai 				     cfg->speaker_pins);
41675ccf835cSTakashi Iwai 		if (err < 0)
41685ccf835cSTakashi Iwai 			return err;
41695ccf835cSTakashi Iwai 	}
41705ccf835cSTakashi Iwai 	return 0;
41715ccf835cSTakashi Iwai }
41725ccf835cSTakashi Iwai 
41735ccf835cSTakashi Iwai /* power up/down beep widget and its output paths */
41745ccf835cSTakashi Iwai static void beep_power_hook(struct hda_beep *beep, bool on)
41755ccf835cSTakashi Iwai {
41765ccf835cSTakashi Iwai 	set_path_power(beep->codec, beep->nid, -1, on);
41775ccf835cSTakashi Iwai }
41785ccf835cSTakashi Iwai 
41796b275b14STakashi Iwai /**
41806b275b14STakashi Iwai  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
41816b275b14STakashi Iwai  * @codec: the HDA codec
41826b275b14STakashi Iwai  * @pin: NID of pin to fix
41836b275b14STakashi Iwai  */
41846b275b14STakashi Iwai int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
41856b275b14STakashi Iwai {
41866b275b14STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41876b275b14STakashi Iwai 	struct nid_path *path;
41886b275b14STakashi Iwai 
41896b275b14STakashi Iwai 	path = snd_array_new(&spec->paths);
41906b275b14STakashi Iwai 	if (!path)
41916b275b14STakashi Iwai 		return -ENOMEM;
41926b275b14STakashi Iwai 	memset(path, 0, sizeof(*path));
41936b275b14STakashi Iwai 	path->depth = 1;
41946b275b14STakashi Iwai 	path->path[0] = pin;
41956b275b14STakashi Iwai 	path->active = true;
41966b275b14STakashi Iwai 	path->pin_fixed = true;
41976b275b14STakashi Iwai 	path->stream_enabled = true;
41986b275b14STakashi Iwai 	return 0;
41996b275b14STakashi Iwai }
42006b275b14STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
42016b275b14STakashi Iwai 
42021da177e4SLinus Torvalds /*
4203352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
42041da177e4SLinus Torvalds  */
4205352f7f91STakashi Iwai 
4206352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
4207352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
42081da177e4SLinus Torvalds {
420960ea8ca2STakashi Iwai 	int i;
421060ea8ca2STakashi Iwai 	bool present = false;
42111da177e4SLinus Torvalds 
4212352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4213352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4214352f7f91STakashi Iwai 		if (!nid)
4215352f7f91STakashi Iwai 			break;
42160b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
42170b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
42180b4df931STakashi Iwai 			continue;
421960ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
422060ea8ca2STakashi Iwai 			present = true;
42211da177e4SLinus Torvalds 	}
4222352f7f91STakashi Iwai 	return present;
42231da177e4SLinus Torvalds }
42241da177e4SLinus Torvalds 
4225352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
4226352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
4227e80c60f3STakashi Iwai 			int *paths, bool mute)
42281da177e4SLinus Torvalds {
4229352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4230352f7f91STakashi Iwai 	int i;
42311da177e4SLinus Torvalds 
4232352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4233352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4234967303daSTakashi Iwai 		unsigned int val, oldval;
4235352f7f91STakashi Iwai 		if (!nid)
4236352f7f91STakashi Iwai 			break;
42377eebffd3STakashi Iwai 
4238e6feb5d0STakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4239e6feb5d0STakashi Iwai 		if (oldval & PIN_IN)
4240e6feb5d0STakashi Iwai 			continue; /* no mute for inputs */
4241e6feb5d0STakashi Iwai 
42427eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
4243e80c60f3STakashi Iwai 			struct nid_path *path;
4244e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
4245e80c60f3STakashi Iwai 
4246e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4247e80c60f3STakashi Iwai 			if (!path)
4248e80c60f3STakashi Iwai 				continue;
4249e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4250e80c60f3STakashi Iwai 			if (!mute_nid)
4251e80c60f3STakashi Iwai 				continue;
42527eebffd3STakashi Iwai 			if (mute)
4253e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
42547eebffd3STakashi Iwai 			else
4255e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
42567eebffd3STakashi Iwai 			continue;
4257e6feb5d0STakashi Iwai 		} else {
4258352f7f91STakashi Iwai 			/* don't reset VREF value in case it's controlling
4259352f7f91STakashi Iwai 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4260352f7f91STakashi Iwai 			 */
42612c12c30dSTakashi Iwai 			if (spec->keep_vref_in_automute)
4262967303daSTakashi Iwai 				val = oldval & ~PIN_HP;
42632c12c30dSTakashi Iwai 			else
4264352f7f91STakashi Iwai 				val = 0;
42652c12c30dSTakashi Iwai 			if (!mute)
4266967303daSTakashi Iwai 				val |= oldval;
4267e6feb5d0STakashi Iwai 			/* here we call update_pin_ctl() so that the pinctl is
4268e6feb5d0STakashi Iwai 			 * changed without changing the pinctl target value;
4269e6feb5d0STakashi Iwai 			 * the original target value will be still referred at
4270e6feb5d0STakashi Iwai 			 * the init / resume again
42712c12c30dSTakashi Iwai 			 */
42722c12c30dSTakashi Iwai 			update_pin_ctl(codec, nid, val);
4273e6feb5d0STakashi Iwai 		}
4274e6feb5d0STakashi Iwai 
4275d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
4276967b1307STakashi Iwai 		if (codec->power_save_node) {
4277e6feb5d0STakashi Iwai 			bool on = !mute;
4278e6feb5d0STakashi Iwai 			if (on)
4279d5ac0100STakashi Iwai 				on = detect_pin_state(codec, nid);
4280e6feb5d0STakashi Iwai 			set_path_power(codec, nid, on, -1);
4281e6feb5d0STakashi Iwai 		}
4282352f7f91STakashi Iwai 	}
4283352f7f91STakashi Iwai }
42841da177e4SLinus Torvalds 
4285dda42bd0STakashi Iwai /**
4286dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
4287dda42bd0STakashi Iwai  * @codec: the HDA codec
4288dda42bd0STakashi Iwai  *
4289dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
4290dda42bd0STakashi Iwai  */
42915d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
4292352f7f91STakashi Iwai {
4293352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4294e80c60f3STakashi Iwai 	int *paths;
4295352f7f91STakashi Iwai 	int on;
4296352f7f91STakashi Iwai 
4297352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
4298352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
4299352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
4300352f7f91STakashi Iwai 	 */
4301e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4302e80c60f3STakashi Iwai 		paths = spec->out_paths;
4303e80c60f3STakashi Iwai 	else
4304e80c60f3STakashi Iwai 		paths = spec->hp_paths;
4305352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4306e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4307352f7f91STakashi Iwai 
4308352f7f91STakashi Iwai 	if (!spec->automute_speaker)
4309352f7f91STakashi Iwai 		on = 0;
4310352f7f91STakashi Iwai 	else
4311352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
4312352f7f91STakashi Iwai 	on |= spec->master_mute;
431347b9ddb8STakashi Iwai 	spec->speaker_muted = on;
4314e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4315e80c60f3STakashi Iwai 		paths = spec->out_paths;
4316e80c60f3STakashi Iwai 	else
4317e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
4318352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4319e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
4320352f7f91STakashi Iwai 
4321352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
4322352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4323352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4324352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4325352f7f91STakashi Iwai 		return;
4326352f7f91STakashi Iwai 	if (!spec->automute_lo)
4327352f7f91STakashi Iwai 		on = 0;
4328352f7f91STakashi Iwai 	else
4329352f7f91STakashi Iwai 		on = spec->hp_jack_present;
4330352f7f91STakashi Iwai 	on |= spec->master_mute;
433147b9ddb8STakashi Iwai 	spec->line_out_muted = on;
4332e80c60f3STakashi Iwai 	paths = spec->out_paths;
4333352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4334e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
4335352f7f91STakashi Iwai }
43362698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4337352f7f91STakashi Iwai 
4338352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
4339352f7f91STakashi Iwai {
4340352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4341352f7f91STakashi Iwai 	if (spec->automute_hook)
4342352f7f91STakashi Iwai 		spec->automute_hook(codec);
4343352f7f91STakashi Iwai 	else
43445d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
43457eebffd3STakashi Iwai 
43467eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
43477eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
43487eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4349352f7f91STakashi Iwai }
4350352f7f91STakashi Iwai 
4351dda42bd0STakashi Iwai /**
4352dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4353dda42bd0STakashi Iwai  * @codec: the HDA codec
4354dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4355dda42bd0STakashi Iwai  */
43561a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
43571a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4358352f7f91STakashi Iwai {
4359352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
436092603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
436192603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4362352f7f91STakashi Iwai 
436392603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
436492603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
436592603c59STakashi Iwai 		pins++;
436692603c59STakashi Iwai 		num_pins--;
436792603c59STakashi Iwai 	}
436892603c59STakashi Iwai 
436992603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4370352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4371352f7f91STakashi Iwai 		return;
4372352f7f91STakashi Iwai 	call_update_outputs(codec);
4373352f7f91STakashi Iwai }
43742698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4375352f7f91STakashi Iwai 
4376dda42bd0STakashi Iwai /**
4377dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4378dda42bd0STakashi Iwai  * @codec: the HDA codec
4379dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4380dda42bd0STakashi Iwai  */
43811a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
43821a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4383352f7f91STakashi Iwai {
4384352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4385352f7f91STakashi Iwai 
4386352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4387352f7f91STakashi Iwai 		return;
4388352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4389352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4390352f7f91STakashi Iwai 		return;
4391352f7f91STakashi Iwai 
4392352f7f91STakashi Iwai 	spec->line_jack_present =
4393352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4394352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4395352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4396352f7f91STakashi Iwai 		return;
4397352f7f91STakashi Iwai 	call_update_outputs(codec);
4398352f7f91STakashi Iwai }
43992698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4400352f7f91STakashi Iwai 
4401dda42bd0STakashi Iwai /**
4402dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4403dda42bd0STakashi Iwai  * @codec: the HDA codec
4404dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4405dda42bd0STakashi Iwai  */
44061a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
44071a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4408352f7f91STakashi Iwai {
4409352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4410352f7f91STakashi Iwai 	int i;
4411352f7f91STakashi Iwai 
4412352f7f91STakashi Iwai 	if (!spec->auto_mic)
4413352f7f91STakashi Iwai 		return;
4414352f7f91STakashi Iwai 
4415352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
44160b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
44170b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
44180b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
44190b4df931STakashi Iwai 			continue;
442060ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4421352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4422352f7f91STakashi Iwai 			return;
4423352f7f91STakashi Iwai 		}
4424352f7f91STakashi Iwai 	}
4425352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
44261da177e4SLinus Torvalds }
44272698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
44281da177e4SLinus Torvalds 
442977afe0e9STakashi Iwai /* call appropriate hooks */
44301a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
44311a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
443277afe0e9STakashi Iwai {
443377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
443477afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
443577afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
443677afe0e9STakashi Iwai 	else
443777afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
443877afe0e9STakashi Iwai }
443977afe0e9STakashi Iwai 
444077afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
44411a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
444277afe0e9STakashi Iwai {
444377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
444477afe0e9STakashi Iwai 	if (spec->line_automute_hook)
444577afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
444677afe0e9STakashi Iwai 	else
444777afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
444877afe0e9STakashi Iwai }
444977afe0e9STakashi Iwai 
445077afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
44511a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
445277afe0e9STakashi Iwai {
445377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
445477afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
445577afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
445677afe0e9STakashi Iwai 	else
445777afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
445877afe0e9STakashi Iwai }
445977afe0e9STakashi Iwai 
4460963afde9STakashi Iwai /* update jack retasking */
4461963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4462963afde9STakashi Iwai {
4463963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4464963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4465963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4466963afde9STakashi Iwai }
4467963afde9STakashi Iwai 
44681da177e4SLinus Torvalds /*
4469352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
44701da177e4SLinus Torvalds  */
4471352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4472352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4473352f7f91STakashi Iwai {
4474352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4475352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4476352f7f91STakashi Iwai 	static const char * const texts3[] = {
4477352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
44781da177e4SLinus Torvalds 	};
44791da177e4SLinus Torvalds 
4480352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4481352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4482352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4483352f7f91STakashi Iwai }
4484352f7f91STakashi Iwai 
4485352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4486352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4487352f7f91STakashi Iwai {
4488352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4489352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4490352f7f91STakashi Iwai 	unsigned int val = 0;
4491352f7f91STakashi Iwai 	if (spec->automute_speaker)
4492352f7f91STakashi Iwai 		val++;
4493352f7f91STakashi Iwai 	if (spec->automute_lo)
4494352f7f91STakashi Iwai 		val++;
4495352f7f91STakashi Iwai 
4496352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4497352f7f91STakashi Iwai 	return 0;
4498352f7f91STakashi Iwai }
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4501352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4502352f7f91STakashi Iwai {
4503352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4504352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4505352f7f91STakashi Iwai 
4506352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4507352f7f91STakashi Iwai 	case 0:
4508352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4509352f7f91STakashi Iwai 			return 0;
4510352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4511352f7f91STakashi Iwai 		spec->automute_lo = 0;
4512352f7f91STakashi Iwai 		break;
4513352f7f91STakashi Iwai 	case 1:
4514352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4515352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4516352f7f91STakashi Iwai 				return 0;
4517352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4518352f7f91STakashi Iwai 			spec->automute_lo = 0;
4519352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4520352f7f91STakashi Iwai 			if (spec->automute_lo)
4521352f7f91STakashi Iwai 				return 0;
4522352f7f91STakashi Iwai 			spec->automute_lo = 1;
4523352f7f91STakashi Iwai 		} else
4524352f7f91STakashi Iwai 			return -EINVAL;
4525352f7f91STakashi Iwai 		break;
4526352f7f91STakashi Iwai 	case 2:
4527352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4528352f7f91STakashi Iwai 			return -EINVAL;
4529352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4530352f7f91STakashi Iwai 			return 0;
4531352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4532352f7f91STakashi Iwai 		spec->automute_lo = 1;
4533352f7f91STakashi Iwai 		break;
4534352f7f91STakashi Iwai 	default:
4535352f7f91STakashi Iwai 		return -EINVAL;
4536352f7f91STakashi Iwai 	}
4537352f7f91STakashi Iwai 	call_update_outputs(codec);
4538352f7f91STakashi Iwai 	return 1;
4539352f7f91STakashi Iwai }
4540352f7f91STakashi Iwai 
4541352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4542352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4543352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4544352f7f91STakashi Iwai 	.info = automute_mode_info,
4545352f7f91STakashi Iwai 	.get = automute_mode_get,
4546352f7f91STakashi Iwai 	.put = automute_mode_put,
4547352f7f91STakashi Iwai };
4548352f7f91STakashi Iwai 
4549352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4550352f7f91STakashi Iwai {
4551352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4552352f7f91STakashi Iwai 
455312c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4554352f7f91STakashi Iwai 		return -ENOMEM;
4555352f7f91STakashi Iwai 	return 0;
4556352f7f91STakashi Iwai }
4557352f7f91STakashi Iwai 
4558352f7f91STakashi Iwai /*
4559352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4560352f7f91STakashi Iwai  * Set up appropriately if really supported
4561352f7f91STakashi Iwai  */
4562352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4563352f7f91STakashi Iwai {
4564352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4565352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4566352f7f91STakashi Iwai 	int present = 0;
4567352f7f91STakashi Iwai 	int i, err;
4568352f7f91STakashi Iwai 
4569f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4570f72706beSTakashi Iwai 		return 0;
4571f72706beSTakashi Iwai 
4572352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4573352f7f91STakashi Iwai 		present++;
4574352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4575352f7f91STakashi Iwai 		present++;
4576352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4577352f7f91STakashi Iwai 		present++;
4578352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4579352f7f91STakashi Iwai 		return 0;
4580352f7f91STakashi Iwai 
4581352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4582352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4583352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4584352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4585352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4586352f7f91STakashi Iwai 	}
4587352f7f91STakashi Iwai 
4588352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4589352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4590352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4591352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4592352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4593352f7f91STakashi Iwai 	}
4594352f7f91STakashi Iwai 
4595352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4596352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4597352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4598352f7f91STakashi Iwai 			continue;
45994e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
460062f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
460177afe0e9STakashi Iwai 						    call_hp_automute);
4602352f7f91STakashi Iwai 		spec->detect_hp = 1;
4603352f7f91STakashi Iwai 	}
4604352f7f91STakashi Iwai 
4605352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4606352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4607352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4608352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4609352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4610352f7f91STakashi Iwai 					continue;
46114e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4612352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
461377afe0e9STakashi Iwai 								    call_line_automute);
4614352f7f91STakashi Iwai 				spec->detect_lo = 1;
4615352f7f91STakashi Iwai 			}
4616352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4617352f7f91STakashi Iwai 	}
4618352f7f91STakashi Iwai 
4619352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4620352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4621352f7f91STakashi Iwai 
4622352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4623352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4624352f7f91STakashi Iwai 
4625352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4626352f7f91STakashi Iwai 		/* create a control for automute mode */
4627352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4628352f7f91STakashi Iwai 		if (err < 0)
4629352f7f91STakashi Iwai 			return err;
4630352f7f91STakashi Iwai 	}
4631352f7f91STakashi Iwai 	return 0;
4632352f7f91STakashi Iwai }
4633352f7f91STakashi Iwai 
4634352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4635352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4636352f7f91STakashi Iwai {
4637352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4638352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4639352f7f91STakashi Iwai 	int i;
4640352f7f91STakashi Iwai 
4641352f7f91STakashi Iwai 	imux = &spec->input_mux;
4642352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4643352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4644352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4645352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4646352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4647352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4648352f7f91STakashi Iwai 	}
4649352f7f91STakashi Iwai 
4650352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4651352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4652352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4653352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
465477afe0e9STakashi Iwai 						    call_mic_autoswitch);
4655352f7f91STakashi Iwai 	return true;
4656352f7f91STakashi Iwai }
4657352f7f91STakashi Iwai 
4658352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4659352f7f91STakashi Iwai {
4660352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4661352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4662352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4663352f7f91STakashi Iwai }
4664352f7f91STakashi Iwai 
4665352f7f91STakashi Iwai /*
4666352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4667352f7f91STakashi Iwai  * Set up if really supported
4668352f7f91STakashi Iwai  */
4669352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4670352f7f91STakashi Iwai {
4671352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4672352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4673352f7f91STakashi Iwai 	unsigned int types;
4674352f7f91STakashi Iwai 	int i, num_pins;
4675352f7f91STakashi Iwai 
4676d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4677d12daf6fSTakashi Iwai 		return 0;
4678d12daf6fSTakashi Iwai 
4679352f7f91STakashi Iwai 	types = 0;
4680352f7f91STakashi Iwai 	num_pins = 0;
4681352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4682352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4683352f7f91STakashi Iwai 		unsigned int attr;
4684352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4685352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4686352f7f91STakashi Iwai 		if (types & (1 << attr))
4687352f7f91STakashi Iwai 			return 0; /* already occupied */
4688352f7f91STakashi Iwai 		switch (attr) {
4689352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4690352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4691352f7f91STakashi Iwai 				return 0; /* invalid type */
4692352f7f91STakashi Iwai 			break;
4693352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4694352f7f91STakashi Iwai 			return 0; /* invalid entry */
4695352f7f91STakashi Iwai 		default:
4696352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4697352f7f91STakashi Iwai 				return 0; /* invalid type */
4698352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4699352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4700352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4701352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4702352f7f91STakashi Iwai 				return 0; /* no unsol support */
4703352f7f91STakashi Iwai 			break;
4704352f7f91STakashi Iwai 		}
4705352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4706352f7f91STakashi Iwai 			return 0;
4707352f7f91STakashi Iwai 		types |= (1 << attr);
4708352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4709352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4710352f7f91STakashi Iwai 		num_pins++;
4711352f7f91STakashi Iwai 	}
4712352f7f91STakashi Iwai 
4713352f7f91STakashi Iwai 	if (num_pins < 2)
4714352f7f91STakashi Iwai 		return 0;
4715352f7f91STakashi Iwai 
4716352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4717352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4718352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4719352f7f91STakashi Iwai 	 */
4720352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4721352f7f91STakashi Iwai 	     compare_attr, NULL);
4722352f7f91STakashi Iwai 
4723352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4724352f7f91STakashi Iwai 		return 0;
4725352f7f91STakashi Iwai 
4726352f7f91STakashi Iwai 	spec->auto_mic = 1;
4727352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4728352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
47294e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4730352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4731352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4732352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4733352f7f91STakashi Iwai 
4734352f7f91STakashi Iwai 	return 0;
4735352f7f91STakashi Iwai }
4736352f7f91STakashi Iwai 
4737dda42bd0STakashi Iwai /**
4738dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4739dda42bd0STakashi Iwai  * into power down
4740dda42bd0STakashi Iwai  * @codec: the HDA codec
4741dda42bd0STakashi Iwai  * @nid: NID to evalute
4742dda42bd0STakashi Iwai  * @power_state: target power state
4743dda42bd0STakashi Iwai  */
4744dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
474555196fffSTakashi Iwai 						  hda_nid_t nid,
474655196fffSTakashi Iwai 						  unsigned int power_state)
474755196fffSTakashi Iwai {
4748b6c09b3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4749b6c09b3cSTakashi Iwai 
4750b6c09b3cSTakashi Iwai 	if (!spec->power_down_unused && !codec->power_save_node)
4751b6c09b3cSTakashi Iwai 		return power_state;
47527639a06cSTakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
475355196fffSTakashi Iwai 		return power_state;
475455196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
475555196fffSTakashi Iwai 		return power_state;
4756b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
475755196fffSTakashi Iwai 		return power_state;
475855196fffSTakashi Iwai 	return AC_PWRST_D3;
475955196fffSTakashi Iwai }
4760dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
476155196fffSTakashi Iwai 
4762ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4763ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4764ebb93c05STakashi Iwai {
4765ebb93c05STakashi Iwai 	int i, nums;
4766ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4767ebb93c05STakashi Iwai 	bool has_amp;
4768ebb93c05STakashi Iwai 
4769ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4770ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4771ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4772ebb93c05STakashi Iwai 		if (has_amp)
4773ef403edbSTakashi Iwai 			update_amp(codec, mix, HDA_INPUT, i,
4774ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4775ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4776ef403edbSTakashi Iwai 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
4777ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4778ebb93c05STakashi Iwai 	}
4779ebb93c05STakashi Iwai }
4780352f7f91STakashi Iwai 
4781dda42bd0STakashi Iwai /**
4782e6feb5d0STakashi Iwai  * snd_hda_gen_stream_pm - Stream power management callback
4783e6feb5d0STakashi Iwai  * @codec: the HDA codec
4784e6feb5d0STakashi Iwai  * @nid: audio widget
4785e6feb5d0STakashi Iwai  * @on: power on/off flag
4786e6feb5d0STakashi Iwai  *
4787967b1307STakashi Iwai  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
4788e6feb5d0STakashi Iwai  */
4789e6feb5d0STakashi Iwai void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
4790e6feb5d0STakashi Iwai {
4791967b1307STakashi Iwai 	if (codec->power_save_node)
4792e6feb5d0STakashi Iwai 		set_path_power(codec, nid, -1, on);
4793e6feb5d0STakashi Iwai }
4794e6feb5d0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
4795e6feb5d0STakashi Iwai 
4796e6feb5d0STakashi Iwai /**
4797dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
4798dda42bd0STakashi Iwai  * set up the hda_gen_spec
4799dda42bd0STakashi Iwai  * @codec: the HDA codec
4800dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
48019eb413e5STakashi Iwai  *
48029eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4803352f7f91STakashi Iwai  * or a negative error code
4804352f7f91STakashi Iwai  */
4805352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
48069eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4807352f7f91STakashi Iwai {
4808352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4809352f7f91STakashi Iwai 	int err;
4810352f7f91STakashi Iwai 
48111c70a583STakashi Iwai 	parse_user_hints(codec);
48121c70a583STakashi Iwai 
4813e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4814e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4815e4a395e7STakashi Iwai 
48169eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
48179eb413e5STakashi Iwai 		spec->autocfg = *cfg;
48189eb413e5STakashi Iwai 		cfg = &spec->autocfg;
48199eb413e5STakashi Iwai 	}
48209eb413e5STakashi Iwai 
482198bd1115STakashi Iwai 	if (!spec->main_out_badness)
482298bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
482398bd1115STakashi Iwai 	if (!spec->extra_out_badness)
482498bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
482598bd1115STakashi Iwai 
48266fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
48276fc4cb97SDavid Henningsson 
4828352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4829352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4830352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4831352f7f91STakashi Iwai 			spec->no_analog = 1;
4832352f7f91STakashi Iwai 			goto dig_only;
4833352f7f91STakashi Iwai 		}
4834c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4835352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4836352f7f91STakashi Iwai 	}
4837352f7f91STakashi Iwai 
4838352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4839352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4840352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4841352f7f91STakashi Iwai 		/* use HP as primary out */
4842352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4843352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4844352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4845352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4846352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4847352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4848352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4849352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4850352f7f91STakashi Iwai 	}
4851352f7f91STakashi Iwai 
4852352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4853352f7f91STakashi Iwai 	if (err < 0)
4854352f7f91STakashi Iwai 		return err;
4855352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4856352f7f91STakashi Iwai 	if (err < 0)
4857352f7f91STakashi Iwai 		return err;
4858352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4859352f7f91STakashi Iwai 	if (err < 0)
4860352f7f91STakashi Iwai 		return err;
4861352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4862352f7f91STakashi Iwai 	if (err < 0)
4863352f7f91STakashi Iwai 		return err;
4864352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4865352f7f91STakashi Iwai 	if (err < 0)
4866352f7f91STakashi Iwai 		return err;
486738cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
486838cf6f1aSTakashi Iwai 	if (err < 0)
486938cf6f1aSTakashi Iwai 		return err;
4870c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4871c30aa7b2STakashi Iwai 	if (err < 0)
4872c30aa7b2STakashi Iwai 		return err;
4873967303daSTakashi Iwai 	err = create_hp_mic(codec);
4874352f7f91STakashi Iwai 	if (err < 0)
4875352f7f91STakashi Iwai 		return err;
4876352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4877352f7f91STakashi Iwai 	if (err < 0)
4878352f7f91STakashi Iwai 		return err;
4879352f7f91STakashi Iwai 
4880e6feb5d0STakashi Iwai 	/* add power-down pin callbacks at first */
4881e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, false);
4882e6feb5d0STakashi Iwai 
4883a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4884a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4885a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4886a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4887a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4888a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4889a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4890a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4891352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4892352f7f91STakashi Iwai 					  spec->const_channel_count);
4893352f7f91STakashi Iwai 
4894352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4895352f7f91STakashi Iwai 	if (err < 0)
4896352f7f91STakashi Iwai 		return err;
4897352f7f91STakashi Iwai 
4898352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4899352f7f91STakashi Iwai 	if (err < 0)
4900352f7f91STakashi Iwai 		return err;
4901352f7f91STakashi Iwai 
4902352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4903352f7f91STakashi Iwai 	if (err < 0)
4904352f7f91STakashi Iwai 		return err;
4905352f7f91STakashi Iwai 
4906f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
4907f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
490874f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
490974f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
4910f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
4911f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
4912f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
4913f1e762ddSTakashi Iwai 		if (err < 0)
4914f1e762ddSTakashi Iwai 			return err;
4915f1e762ddSTakashi Iwai 	}
4916f1e762ddSTakashi Iwai 
4917f1e762ddSTakashi Iwai 
4918352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4919352f7f91STakashi Iwai 	if (err < 0)
4920352f7f91STakashi Iwai 		return err;
4921352f7f91STakashi Iwai 
4922352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4923352f7f91STakashi Iwai 	if (err < 0)
4924352f7f91STakashi Iwai 		return err;
4925352f7f91STakashi Iwai 
4926ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4927ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4928ced4cefcSTakashi Iwai 	 */
4929ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4930ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4931ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4932ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4933ced4cefcSTakashi Iwai 		if (err < 0)
4934ced4cefcSTakashi Iwai 			return err;
4935ced4cefcSTakashi Iwai 	}
4936ced4cefcSTakashi Iwai 
4937f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4938978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4939978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4940978e77e7STakashi Iwai 						    cfg->line_out_pins);
4941978e77e7STakashi Iwai 			if (err < 0)
4942978e77e7STakashi Iwai 				return err;
4943978e77e7STakashi Iwai 		}
4944978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4945978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4946978e77e7STakashi Iwai 						    cfg->hp_pins);
4947978e77e7STakashi Iwai 			if (err < 0)
4948978e77e7STakashi Iwai 				return err;
4949978e77e7STakashi Iwai 		}
4950978e77e7STakashi Iwai 	}
4951978e77e7STakashi Iwai 
4952e6feb5d0STakashi Iwai 	/* add power-up pin callbacks at last */
4953e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, true);
4954e6feb5d0STakashi Iwai 
4955ebb93c05STakashi Iwai 	/* mute all aamix input initially */
4956ebb93c05STakashi Iwai 	if (spec->mixer_nid)
4957ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
4958ebb93c05STakashi Iwai 
4959352f7f91STakashi Iwai  dig_only:
4960352f7f91STakashi Iwai 	parse_digital(codec);
4961352f7f91STakashi Iwai 
496249fb1897STakashi Iwai 	if (spec->power_down_unused || codec->power_save_node) {
496324fef902STakashi Iwai 		if (!codec->power_filter)
496455196fffSTakashi Iwai 			codec->power_filter = snd_hda_gen_path_power_filter;
496549fb1897STakashi Iwai 		if (!codec->patch_ops.stream_pm)
496649fb1897STakashi Iwai 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
496749fb1897STakashi Iwai 	}
496855196fffSTakashi Iwai 
49697504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
49707504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
49717504b6cdSTakashi Iwai 		if (err < 0)
49727504b6cdSTakashi Iwai 			return err;
4973967b1307STakashi Iwai 		if (codec->beep && codec->power_save_node) {
49745ccf835cSTakashi Iwai 			err = add_fake_beep_paths(codec);
49755ccf835cSTakashi Iwai 			if (err < 0)
49765ccf835cSTakashi Iwai 				return err;
49775ccf835cSTakashi Iwai 			codec->beep->power_hook = beep_power_hook;
49785ccf835cSTakashi Iwai 		}
49797504b6cdSTakashi Iwai 	}
49807504b6cdSTakashi Iwai 
4981352f7f91STakashi Iwai 	return 1;
4982352f7f91STakashi Iwai }
49832698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
4984352f7f91STakashi Iwai 
4985352f7f91STakashi Iwai 
4986352f7f91STakashi Iwai /*
4987352f7f91STakashi Iwai  * Build control elements
4988352f7f91STakashi Iwai  */
4989352f7f91STakashi Iwai 
4990352f7f91STakashi Iwai /* slave controls for virtual master */
4991352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4992352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4993352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4994352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4995ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4996ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
499703ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
4998352f7f91STakashi Iwai 	NULL,
4999352f7f91STakashi Iwai };
5000352f7f91STakashi Iwai 
5001dda42bd0STakashi Iwai /**
5002dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
5003dda42bd0STakashi Iwai  * @codec: the HDA codec
5004dda42bd0STakashi Iwai  *
5005dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
5006dda42bd0STakashi Iwai  */
5007352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
5008352f7f91STakashi Iwai {
5009352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5010352f7f91STakashi Iwai 	int err;
5011352f7f91STakashi Iwai 
501236502d02STakashi Iwai 	if (spec->kctls.used) {
5013352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5014352f7f91STakashi Iwai 		if (err < 0)
5015352f7f91STakashi Iwai 			return err;
501636502d02STakashi Iwai 	}
5017352f7f91STakashi Iwai 
5018352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
5019352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
5020352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5021352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5022bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
5023352f7f91STakashi Iwai 		if (err < 0)
5024352f7f91STakashi Iwai 			return err;
5025352f7f91STakashi Iwai 		if (!spec->no_analog) {
5026352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
5027352f7f91STakashi Iwai 							    &spec->multiout);
5028352f7f91STakashi Iwai 			if (err < 0)
5029352f7f91STakashi Iwai 				return err;
5030352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
5031352f7f91STakashi Iwai 		}
5032352f7f91STakashi Iwai 	}
5033352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
5034352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5035352f7f91STakashi Iwai 		if (err < 0)
5036352f7f91STakashi Iwai 			return err;
5037352f7f91STakashi Iwai 	}
5038352f7f91STakashi Iwai 
5039352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
50407480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5041352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5042352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
50437a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
5044352f7f91STakashi Iwai 					  "Playback Volume");
5045352f7f91STakashi Iwai 		if (err < 0)
5046352f7f91STakashi Iwai 			return err;
5047352f7f91STakashi Iwai 	}
50487480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5049352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5050352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
5051352f7f91STakashi Iwai 					    NULL, slave_pfxs,
5052352f7f91STakashi Iwai 					    "Playback Switch",
5053352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
5054352f7f91STakashi Iwai 		if (err < 0)
5055352f7f91STakashi Iwai 			return err;
5056b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
5057fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
5058fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
5059b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5060b63eae0aSTakashi Iwai 		}
5061352f7f91STakashi Iwai 	}
5062352f7f91STakashi Iwai 
5063352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
5064352f7f91STakashi Iwai 
5065352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5066352f7f91STakashi Iwai 	if (err < 0)
5067352f7f91STakashi Iwai 		return err;
5068352f7f91STakashi Iwai 
5069352f7f91STakashi Iwai 	return 0;
5070352f7f91STakashi Iwai }
50712698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5072352f7f91STakashi Iwai 
5073352f7f91STakashi Iwai 
5074352f7f91STakashi Iwai /*
5075352f7f91STakashi Iwai  * PCM definitions
5076352f7f91STakashi Iwai  */
5077352f7f91STakashi Iwai 
5078e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5079e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
5080e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
5081e6b85f3cSTakashi Iwai 				   int action)
5082e6b85f3cSTakashi Iwai {
5083e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5084e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
5085e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5086e6b85f3cSTakashi Iwai }
5087e6b85f3cSTakashi Iwai 
5088ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5089ac2e8736STakashi Iwai 				  struct hda_codec *codec,
5090ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
5091ac2e8736STakashi Iwai 				  int action)
5092ac2e8736STakashi Iwai {
5093ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5094ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
5095ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5096ac2e8736STakashi Iwai }
5097ac2e8736STakashi Iwai 
5098352f7f91STakashi Iwai /*
5099352f7f91STakashi Iwai  * Analog playback callbacks
5100352f7f91STakashi Iwai  */
5101352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5102352f7f91STakashi Iwai 			     struct hda_codec *codec,
5103352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
5104352f7f91STakashi Iwai {
5105352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
510638cf6f1aSTakashi Iwai 	int err;
510738cf6f1aSTakashi Iwai 
510838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
510938cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
511038cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
5111352f7f91STakashi Iwai 					     hinfo);
5112e6b85f3cSTakashi Iwai 	if (!err) {
511338cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5114e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5115e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
5116e6b85f3cSTakashi Iwai 	}
511738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
511838cf6f1aSTakashi Iwai 	return err;
5119352f7f91STakashi Iwai }
5120352f7f91STakashi Iwai 
5121352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
512297ec558aSTakashi Iwai 				struct hda_codec *codec,
512397ec558aSTakashi Iwai 				unsigned int stream_tag,
512497ec558aSTakashi Iwai 				unsigned int format,
512597ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
512697ec558aSTakashi Iwai {
5127352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5128e6b85f3cSTakashi Iwai 	int err;
5129e6b85f3cSTakashi Iwai 
5130e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5131352f7f91STakashi Iwai 					       stream_tag, format, substream);
5132e6b85f3cSTakashi Iwai 	if (!err)
5133e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5134e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
5135e6b85f3cSTakashi Iwai 	return err;
5136352f7f91STakashi Iwai }
513797ec558aSTakashi Iwai 
5138352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5139352f7f91STakashi Iwai 				struct hda_codec *codec,
5140352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
5141352f7f91STakashi Iwai {
5142352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5143e6b85f3cSTakashi Iwai 	int err;
5144e6b85f3cSTakashi Iwai 
5145e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5146e6b85f3cSTakashi Iwai 	if (!err)
5147e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5148e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
5149e6b85f3cSTakashi Iwai 	return err;
5150352f7f91STakashi Iwai }
5151352f7f91STakashi Iwai 
515238cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
515338cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
515438cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
515538cf6f1aSTakashi Iwai {
515638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
515738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
515838cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5159e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5160e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
516138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
516238cf6f1aSTakashi Iwai 	return 0;
516338cf6f1aSTakashi Iwai }
516438cf6f1aSTakashi Iwai 
5165ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5166ac2e8736STakashi Iwai 			    struct hda_codec *codec,
5167ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
5168ac2e8736STakashi Iwai {
5169ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5170ac2e8736STakashi Iwai 	return 0;
5171ac2e8736STakashi Iwai }
5172ac2e8736STakashi Iwai 
5173ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5174ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5175ac2e8736STakashi Iwai 			       unsigned int stream_tag,
5176ac2e8736STakashi Iwai 			       unsigned int format,
5177ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5178ac2e8736STakashi Iwai {
5179ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5180ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5181ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
5182ac2e8736STakashi Iwai 	return 0;
5183ac2e8736STakashi Iwai }
5184ac2e8736STakashi Iwai 
5185ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5186ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5187ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5188ac2e8736STakashi Iwai {
5189ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5190ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5191ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
5192ac2e8736STakashi Iwai 	return 0;
5193ac2e8736STakashi Iwai }
5194ac2e8736STakashi Iwai 
5195ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5196ac2e8736STakashi Iwai 			     struct hda_codec *codec,
5197ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
5198ac2e8736STakashi Iwai {
5199ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5200ac2e8736STakashi Iwai 	return 0;
5201ac2e8736STakashi Iwai }
5202ac2e8736STakashi Iwai 
520338cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
520438cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
520538cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
520638cf6f1aSTakashi Iwai {
520738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
520838cf6f1aSTakashi Iwai 	int err = 0;
520938cf6f1aSTakashi Iwai 
521038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
5211d1f15e06STakashi Iwai 	if (spec->indep_hp && !spec->indep_hp_enabled)
521238cf6f1aSTakashi Iwai 		err = -EBUSY;
521338cf6f1aSTakashi Iwai 	else
521438cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5215e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5216e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
521738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
521838cf6f1aSTakashi Iwai 	return err;
521938cf6f1aSTakashi Iwai }
522038cf6f1aSTakashi Iwai 
522138cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
522238cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
522338cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
522438cf6f1aSTakashi Iwai {
522538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
522638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
522738cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5228e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5229e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
523038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
523138cf6f1aSTakashi Iwai 	return 0;
523238cf6f1aSTakashi Iwai }
523338cf6f1aSTakashi Iwai 
5234e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5235e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5236e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
5237e6b85f3cSTakashi Iwai 				    unsigned int format,
5238e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5239e6b85f3cSTakashi Iwai {
5240e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5241e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5242e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
5243e6b85f3cSTakashi Iwai 	return 0;
5244e6b85f3cSTakashi Iwai }
5245e6b85f3cSTakashi Iwai 
5246e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5247e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5248e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5249e6b85f3cSTakashi Iwai {
5250e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5251e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5252e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
5253e6b85f3cSTakashi Iwai 	return 0;
5254e6b85f3cSTakashi Iwai }
5255e6b85f3cSTakashi Iwai 
5256352f7f91STakashi Iwai /*
5257352f7f91STakashi Iwai  * Digital out
5258352f7f91STakashi Iwai  */
5259352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5260352f7f91STakashi Iwai 				 struct hda_codec *codec,
5261352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
5262352f7f91STakashi Iwai {
5263352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5264352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5265352f7f91STakashi Iwai }
5266352f7f91STakashi Iwai 
5267352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5268352f7f91STakashi Iwai 				    struct hda_codec *codec,
5269352f7f91STakashi Iwai 				    unsigned int stream_tag,
5270352f7f91STakashi Iwai 				    unsigned int format,
5271352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5272352f7f91STakashi Iwai {
5273352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5274352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5275352f7f91STakashi Iwai 					     stream_tag, format, substream);
5276352f7f91STakashi Iwai }
5277352f7f91STakashi Iwai 
5278352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5279352f7f91STakashi Iwai 				    struct hda_codec *codec,
5280352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5281352f7f91STakashi Iwai {
5282352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5283352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5284352f7f91STakashi Iwai }
5285352f7f91STakashi Iwai 
5286352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5287352f7f91STakashi Iwai 				  struct hda_codec *codec,
5288352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
5289352f7f91STakashi Iwai {
5290352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5291352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5292352f7f91STakashi Iwai }
5293352f7f91STakashi Iwai 
5294352f7f91STakashi Iwai /*
5295352f7f91STakashi Iwai  * Analog capture
5296352f7f91STakashi Iwai  */
5297ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
5298ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
5299ac2e8736STakashi Iwai 
5300352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5301352f7f91STakashi Iwai 				   struct hda_codec *codec,
5302352f7f91STakashi Iwai 				   unsigned int stream_tag,
5303352f7f91STakashi Iwai 				   unsigned int format,
5304352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
5305352f7f91STakashi Iwai {
5306352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5307352f7f91STakashi Iwai 
5308352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
530997ec558aSTakashi Iwai 				   stream_tag, 0, format);
5310ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5311ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
531297ec558aSTakashi Iwai 	return 0;
531397ec558aSTakashi Iwai }
531497ec558aSTakashi Iwai 
5315352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
531697ec558aSTakashi Iwai 				   struct hda_codec *codec,
531797ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
531897ec558aSTakashi Iwai {
5319352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
532097ec558aSTakashi Iwai 
5321352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
5322352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
5323ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5324ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
532597ec558aSTakashi Iwai 	return 0;
532697ec558aSTakashi Iwai }
532797ec558aSTakashi Iwai 
5328352f7f91STakashi Iwai /*
5329352f7f91STakashi Iwai  */
5330352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
5331352f7f91STakashi Iwai 	.substreams = 1,
5332352f7f91STakashi Iwai 	.channels_min = 2,
5333352f7f91STakashi Iwai 	.channels_max = 8,
5334352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5335352f7f91STakashi Iwai 	.ops = {
5336352f7f91STakashi Iwai 		.open = playback_pcm_open,
533738cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
5338352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
5339352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
5340352f7f91STakashi Iwai 	},
5341352f7f91STakashi Iwai };
5342352f7f91STakashi Iwai 
5343352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
5344352f7f91STakashi Iwai 	.substreams = 1,
5345352f7f91STakashi Iwai 	.channels_min = 2,
5346352f7f91STakashi Iwai 	.channels_max = 2,
5347352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5348ac2e8736STakashi Iwai 	.ops = {
5349ac2e8736STakashi Iwai 		.open = capture_pcm_open,
5350ac2e8736STakashi Iwai 		.close = capture_pcm_close,
5351ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
5352ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
5353ac2e8736STakashi Iwai 	},
5354352f7f91STakashi Iwai };
5355352f7f91STakashi Iwai 
5356352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
5357352f7f91STakashi Iwai 	.substreams = 1,
5358352f7f91STakashi Iwai 	.channels_min = 2,
5359352f7f91STakashi Iwai 	.channels_max = 2,
5360352f7f91STakashi Iwai 	/* NID is set in build_pcms */
536138cf6f1aSTakashi Iwai 	.ops = {
536238cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
5363e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
5364e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
5365e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
536638cf6f1aSTakashi Iwai 	},
5367352f7f91STakashi Iwai };
5368352f7f91STakashi Iwai 
5369352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
5370352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
5371352f7f91STakashi Iwai 	.channels_min = 2,
5372352f7f91STakashi Iwai 	.channels_max = 2,
5373352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5374352f7f91STakashi Iwai 	.ops = {
5375ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5376ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5377352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5378352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5379352f7f91STakashi Iwai 	},
5380352f7f91STakashi Iwai };
5381352f7f91STakashi Iwai 
5382352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5383352f7f91STakashi Iwai 	.substreams = 1,
5384352f7f91STakashi Iwai 	.channels_min = 2,
5385352f7f91STakashi Iwai 	.channels_max = 2,
5386352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5387352f7f91STakashi Iwai 	.ops = {
5388352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5389352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5390352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5391352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5392352f7f91STakashi Iwai 	},
5393352f7f91STakashi Iwai };
5394352f7f91STakashi Iwai 
5395352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5396352f7f91STakashi Iwai 	.substreams = 1,
5397352f7f91STakashi Iwai 	.channels_min = 2,
5398352f7f91STakashi Iwai 	.channels_max = 2,
5399352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5400352f7f91STakashi Iwai };
5401352f7f91STakashi Iwai 
5402352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5403352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5404352f7f91STakashi Iwai 	.substreams = 0,
5405352f7f91STakashi Iwai 	.channels_min = 0,
5406352f7f91STakashi Iwai 	.channels_max = 0,
5407352f7f91STakashi Iwai };
5408352f7f91STakashi Iwai 
5409352f7f91STakashi Iwai /*
5410352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5411352f7f91STakashi Iwai  */
5412352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
54131da177e4SLinus Torvalds {
5414352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5415352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
54161da177e4SLinus Torvalds 
5417352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5418352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5419352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5420352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5421352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5422352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5423352f7f91STakashi Iwai 					   spec->cur_adc_format);
5424352f7f91STakashi Iwai 		return true;
5425352f7f91STakashi Iwai 	}
5426352f7f91STakashi Iwai 	return false;
5427352f7f91STakashi Iwai }
5428352f7f91STakashi Iwai 
5429352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5430352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5431352f7f91STakashi Iwai 				       struct hda_codec *codec,
5432352f7f91STakashi Iwai 				       unsigned int stream_tag,
5433352f7f91STakashi Iwai 				       unsigned int format,
5434352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5435352f7f91STakashi Iwai {
5436352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5437352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5438352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5439352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5440352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
54414f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
54421da177e4SLinus Torvalds 	return 0;
54431da177e4SLinus Torvalds }
54441da177e4SLinus Torvalds 
5445352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5446352f7f91STakashi Iwai 				       struct hda_codec *codec,
5447352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5448352f7f91STakashi Iwai {
5449352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5450352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5451352f7f91STakashi Iwai 	spec->cur_adc = 0;
54524f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
5453352f7f91STakashi Iwai 	return 0;
5454352f7f91STakashi Iwai }
5455352f7f91STakashi Iwai 
5456352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5457352f7f91STakashi Iwai 	.substreams = 1,
5458352f7f91STakashi Iwai 	.channels_min = 2,
5459352f7f91STakashi Iwai 	.channels_max = 2,
5460352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5461352f7f91STakashi Iwai 	.ops = {
5462352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5463352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5464352f7f91STakashi Iwai 	},
5465352f7f91STakashi Iwai };
5466352f7f91STakashi Iwai 
5467f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5468f873e536STakashi Iwai 				 const char *chip_name)
5469f873e536STakashi Iwai {
5470f873e536STakashi Iwai 	char *p;
5471f873e536STakashi Iwai 
5472f873e536STakashi Iwai 	if (*str)
5473f873e536STakashi Iwai 		return;
5474f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
5475f873e536STakashi Iwai 
5476f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5477f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5478f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5479f873e536STakashi Iwai 			*p = 0;
5480f873e536STakashi Iwai 			break;
5481f873e536STakashi Iwai 		}
5482f873e536STakashi Iwai 	}
5483f873e536STakashi Iwai 	strlcat(str, sfx, len);
5484f873e536STakashi Iwai }
5485f873e536STakashi Iwai 
5486fb83b635STakashi Iwai /* copy PCM stream info from @default_str, and override non-NULL entries
5487fb83b635STakashi Iwai  * from @spec_str and @nid
5488fb83b635STakashi Iwai  */
5489fb83b635STakashi Iwai static void setup_pcm_stream(struct hda_pcm_stream *str,
5490fb83b635STakashi Iwai 			     const struct hda_pcm_stream *default_str,
5491fb83b635STakashi Iwai 			     const struct hda_pcm_stream *spec_str,
5492fb83b635STakashi Iwai 			     hda_nid_t nid)
5493fb83b635STakashi Iwai {
5494fb83b635STakashi Iwai 	*str = *default_str;
5495fb83b635STakashi Iwai 	if (nid)
5496fb83b635STakashi Iwai 		str->nid = nid;
5497fb83b635STakashi Iwai 	if (spec_str) {
5498fb83b635STakashi Iwai 		if (spec_str->substreams)
5499fb83b635STakashi Iwai 			str->substreams = spec_str->substreams;
5500fb83b635STakashi Iwai 		if (spec_str->channels_min)
5501fb83b635STakashi Iwai 			str->channels_min = spec_str->channels_min;
5502fb83b635STakashi Iwai 		if (spec_str->channels_max)
5503fb83b635STakashi Iwai 			str->channels_max = spec_str->channels_max;
5504fb83b635STakashi Iwai 		if (spec_str->rates)
5505fb83b635STakashi Iwai 			str->rates = spec_str->rates;
5506fb83b635STakashi Iwai 		if (spec_str->formats)
5507fb83b635STakashi Iwai 			str->formats = spec_str->formats;
5508fb83b635STakashi Iwai 		if (spec_str->maxbps)
5509fb83b635STakashi Iwai 			str->maxbps = spec_str->maxbps;
5510fb83b635STakashi Iwai 	}
5511fb83b635STakashi Iwai }
5512fb83b635STakashi Iwai 
5513dda42bd0STakashi Iwai /**
5514dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5515dda42bd0STakashi Iwai  * @codec: the HDA codec
5516dda42bd0STakashi Iwai  *
5517dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5518dda42bd0STakashi Iwai  */
5519352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5520352f7f91STakashi Iwai {
5521352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5522bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5523352f7f91STakashi Iwai 	bool have_multi_adcs;
5524352f7f91STakashi Iwai 
5525352f7f91STakashi Iwai 	if (spec->no_analog)
5526352f7f91STakashi Iwai 		goto skip_analog;
5527352f7f91STakashi Iwai 
5528f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5529f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
55307639a06cSTakashi Iwai 			     " Analog", codec->core.chip_name);
5531bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5532bbbc7e85STakashi Iwai 	if (!info)
5533bbbc7e85STakashi Iwai 		return -ENOMEM;
5534bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5535352f7f91STakashi Iwai 
5536352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5537fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5538fb83b635STakashi Iwai 				 &pcm_analog_playback,
5539fb83b635STakashi Iwai 				 spec->stream_analog_playback,
5540fb83b635STakashi Iwai 				 spec->multiout.dac_nids[0]);
5541352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5542352f7f91STakashi Iwai 			spec->multiout.max_channels;
5543352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5544352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5545352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5546352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5547352f7f91STakashi Iwai 	}
5548352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5549fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5550fb83b635STakashi Iwai 				 (spec->dyn_adc_switch ?
5551fb83b635STakashi Iwai 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5552fb83b635STakashi Iwai 				 spec->stream_analog_capture,
5553fb83b635STakashi Iwai 				 spec->adc_nids[0]);
5554352f7f91STakashi Iwai 	}
5555352f7f91STakashi Iwai 
5556352f7f91STakashi Iwai  skip_analog:
5557352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5558352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5559f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5560352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
55617639a06cSTakashi Iwai 				     " Digital", codec->core.chip_name);
5562bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5563bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5564bbbc7e85STakashi Iwai 		if (!info)
5565bbbc7e85STakashi Iwai 			return -ENOMEM;
5566352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5567bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5568352f7f91STakashi Iwai 		if (spec->dig_out_type)
5569352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5570352f7f91STakashi Iwai 		else
5571352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5572fb83b635STakashi Iwai 		if (spec->multiout.dig_out_nid)
5573fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5574fb83b635STakashi Iwai 					 &pcm_digital_playback,
5575fb83b635STakashi Iwai 					 spec->stream_digital_playback,
5576fb83b635STakashi Iwai 					 spec->multiout.dig_out_nid);
5577fb83b635STakashi Iwai 		if (spec->dig_in_nid)
5578fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5579fb83b635STakashi Iwai 					 &pcm_digital_capture,
5580fb83b635STakashi Iwai 					 spec->stream_digital_capture,
5581fb83b635STakashi Iwai 					 spec->dig_in_nid);
5582352f7f91STakashi Iwai 	}
5583352f7f91STakashi Iwai 
5584352f7f91STakashi Iwai 	if (spec->no_analog)
5585352f7f91STakashi Iwai 		return 0;
5586352f7f91STakashi Iwai 
5587352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5588352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5589352f7f91STakashi Iwai 	 */
5590352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5591352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5592352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5593352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5594a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5595a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
55967639a06cSTakashi Iwai 			     " Alt Analog", codec->core.chip_name);
5597bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5598bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5599bbbc7e85STakashi Iwai 		if (!info)
5600bbbc7e85STakashi Iwai 			return -ENOMEM;
5601bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5602fb83b635STakashi Iwai 		if (spec->alt_dac_nid)
5603fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5604fb83b635STakashi Iwai 					 &pcm_analog_alt_playback,
5605fb83b635STakashi Iwai 					 spec->stream_analog_alt_playback,
5606fb83b635STakashi Iwai 					 spec->alt_dac_nid);
5607fb83b635STakashi Iwai 		else
5608fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5609fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5610352f7f91STakashi Iwai 		if (have_multi_adcs) {
5611fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5612fb83b635STakashi Iwai 					 &pcm_analog_alt_capture,
5613fb83b635STakashi Iwai 					 spec->stream_analog_alt_capture,
5614fb83b635STakashi Iwai 					 spec->adc_nids[1]);
5615352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5616352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5617352f7f91STakashi Iwai 		} else {
5618fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5619fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5620352f7f91STakashi Iwai 		}
56211da177e4SLinus Torvalds 	}
56221da177e4SLinus Torvalds 
56231da177e4SLinus Torvalds 	return 0;
56241da177e4SLinus Torvalds }
56252698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5626352f7f91STakashi Iwai 
5627352f7f91STakashi Iwai 
5628352f7f91STakashi Iwai /*
5629352f7f91STakashi Iwai  * Standard auto-parser initializations
5630352f7f91STakashi Iwai  */
5631352f7f91STakashi Iwai 
5632d4156930STakashi Iwai /* configure the given path as a proper output */
56332c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5634352f7f91STakashi Iwai {
5635352f7f91STakashi Iwai 	struct nid_path *path;
5636d4156930STakashi Iwai 	hda_nid_t pin;
5637352f7f91STakashi Iwai 
5638196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5639d4156930STakashi Iwai 	if (!path || !path->depth)
5640352f7f91STakashi Iwai 		return;
5641d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
56422c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
564365033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
564465033cc8STakashi Iwai 			      aamix_default(codec->spec));
5645e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5646352f7f91STakashi Iwai }
5647352f7f91STakashi Iwai 
5648352f7f91STakashi Iwai /* initialize primary output paths */
5649352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5650352f7f91STakashi Iwai {
5651352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5652352f7f91STakashi Iwai 	int i;
5653352f7f91STakashi Iwai 
5654d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
56552c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5656352f7f91STakashi Iwai }
5657352f7f91STakashi Iwai 
5658db23fd19STakashi Iwai 
56592c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5660352f7f91STakashi Iwai {
5661352f7f91STakashi Iwai 	int i;
5662352f7f91STakashi Iwai 
5663d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
56642c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5665352f7f91STakashi Iwai }
5666db23fd19STakashi Iwai 
5667db23fd19STakashi Iwai /* initialize hp and speaker paths */
5668db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5669db23fd19STakashi Iwai {
5670db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5671db23fd19STakashi Iwai 
5672db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
56732c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5674db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5675db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
56762c12c30dSTakashi Iwai 				 spec->speaker_paths);
5677352f7f91STakashi Iwai }
5678352f7f91STakashi Iwai 
5679352f7f91STakashi Iwai /* initialize multi-io paths */
5680352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5681352f7f91STakashi Iwai {
5682352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5683352f7f91STakashi Iwai 	int i;
5684352f7f91STakashi Iwai 
5685352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5686352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5687352f7f91STakashi Iwai 		struct nid_path *path;
5688196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5689352f7f91STakashi Iwai 		if (!path)
5690352f7f91STakashi Iwai 			continue;
5691352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5692352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
56932c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
569465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
569565033cc8STakashi Iwai 				      aamix_default(spec));
5696352f7f91STakashi Iwai 	}
5697352f7f91STakashi Iwai }
5698352f7f91STakashi Iwai 
56994f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
57004f7f67fbSTakashi Iwai {
57014f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
57024f7f67fbSTakashi Iwai 
57034f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
57044f7f67fbSTakashi Iwai 		return;
5705e7fdd527STakashi Iwai 	if (!has_aamix_out_paths(spec))
5706e7fdd527STakashi Iwai 		return;
57074f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
57084f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
57094f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
57104f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
57114f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
57124f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
57134f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
57144f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
57154f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
57164f7f67fbSTakashi Iwai }
57174f7f67fbSTakashi Iwai 
5718352f7f91STakashi Iwai /* set up input pins and loopback paths */
5719352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5720352f7f91STakashi Iwai {
5721352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5722352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5723352f7f91STakashi Iwai 	int i;
5724352f7f91STakashi Iwai 
5725352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5726352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5727352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
57282c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5729352f7f91STakashi Iwai 
5730352f7f91STakashi Iwai 		/* init loopback inputs */
5731352f7f91STakashi Iwai 		if (spec->mixer_nid) {
57323e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
57333e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5734352f7f91STakashi Iwai 		}
5735352f7f91STakashi Iwai 	}
5736352f7f91STakashi Iwai }
5737352f7f91STakashi Iwai 
5738352f7f91STakashi Iwai /* initialize ADC paths */
5739352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5740352f7f91STakashi Iwai {
5741352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5742352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5743352f7f91STakashi Iwai 	struct nid_path *path;
5744352f7f91STakashi Iwai 	int i, c, nums;
5745352f7f91STakashi Iwai 
5746352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5747352f7f91STakashi Iwai 		nums = 1;
5748352f7f91STakashi Iwai 	else
5749352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5750352f7f91STakashi Iwai 
5751352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5752352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5753c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5754352f7f91STakashi Iwai 			if (path) {
5755352f7f91STakashi Iwai 				bool active = path->active;
5756352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5757352f7f91STakashi Iwai 					active = true;
5758352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5759352f7f91STakashi Iwai 			}
5760352f7f91STakashi Iwai 		}
5761967303daSTakashi Iwai 		if (spec->hp_mic)
5762967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5763352f7f91STakashi Iwai 	}
5764352f7f91STakashi Iwai 
5765352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
57667fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
5767352f7f91STakashi Iwai }
5768352f7f91STakashi Iwai 
5769352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5770352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5771352f7f91STakashi Iwai {
5772352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5773352f7f91STakashi Iwai 	int i;
5774352f7f91STakashi Iwai 	hda_nid_t pin;
5775352f7f91STakashi Iwai 
5776d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
57772c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5778352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
57792430d7b7STakashi Iwai 	if (pin) {
57802c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
57813e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
57822430d7b7STakashi Iwai 	}
5783352f7f91STakashi Iwai }
5784352f7f91STakashi Iwai 
5785973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5786973e4972STakashi Iwai  * invalid unsol tags by some reason
5787973e4972STakashi Iwai  */
5788973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5789973e4972STakashi Iwai {
5790973e4972STakashi Iwai 	int i;
5791973e4972STakashi Iwai 
5792973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5793973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5794973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5795973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5796973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5797973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5798973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5799973e4972STakashi Iwai 	}
5800973e4972STakashi Iwai }
5801973e4972STakashi Iwai 
5802dda42bd0STakashi Iwai /**
5803dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
5804dda42bd0STakashi Iwai  * @codec: the HDA codec
5805dda42bd0STakashi Iwai  *
5806dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
58075187ac16STakashi Iwai  */
5808352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5809352f7f91STakashi Iwai {
5810352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5811352f7f91STakashi Iwai 
5812352f7f91STakashi Iwai 	if (spec->init_hook)
5813352f7f91STakashi Iwai 		spec->init_hook(codec);
5814352f7f91STakashi Iwai 
5815352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5816352f7f91STakashi Iwai 
5817352f7f91STakashi Iwai 	init_multi_out(codec);
5818352f7f91STakashi Iwai 	init_extra_out(codec);
5819352f7f91STakashi Iwai 	init_multi_io(codec);
58204f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5821352f7f91STakashi Iwai 	init_analog_input(codec);
5822352f7f91STakashi Iwai 	init_input_src(codec);
5823352f7f91STakashi Iwai 	init_digital(codec);
5824352f7f91STakashi Iwai 
5825973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5826973e4972STakashi Iwai 
5827e6feb5d0STakashi Iwai 	sync_all_pin_power_ctls(codec);
5828e6feb5d0STakashi Iwai 
5829352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5830a5cc2509STakashi Iwai 	update_automute_all(codec);
5831352f7f91STakashi Iwai 
5832a551d914STakashi Iwai 	regcache_sync(codec->core.regmap);
58333bbcd274STakashi Iwai 
5834352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5835352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5836352f7f91STakashi Iwai 
5837352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5838352f7f91STakashi Iwai 	return 0;
5839352f7f91STakashi Iwai }
58402698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5841fce52a3bSTakashi Iwai 
5842dda42bd0STakashi Iwai /**
5843dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
5844dda42bd0STakashi Iwai  * @codec: the HDA codec
5845dda42bd0STakashi Iwai  *
5846dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
58475187ac16STakashi Iwai  */
5848fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5849fce52a3bSTakashi Iwai {
58508a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
5851fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5852fce52a3bSTakashi Iwai 	kfree(codec->spec);
5853fce52a3bSTakashi Iwai 	codec->spec = NULL;
5854fce52a3bSTakashi Iwai }
58552698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
5856fce52a3bSTakashi Iwai 
5857fce52a3bSTakashi Iwai #ifdef CONFIG_PM
5858dda42bd0STakashi Iwai /**
5859dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
5860dda42bd0STakashi Iwai  * @codec: the HDA codec
5861dda42bd0STakashi Iwai  * @nid: NID to inspect
5862dda42bd0STakashi Iwai  *
5863dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
58645187ac16STakashi Iwai  */
5865fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5866fce52a3bSTakashi Iwai {
5867fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5868fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5869fce52a3bSTakashi Iwai }
58702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
5871fce52a3bSTakashi Iwai #endif
5872352f7f91STakashi Iwai 
5873352f7f91STakashi Iwai 
5874352f7f91STakashi Iwai /*
5875352f7f91STakashi Iwai  * the generic codec support
5876352f7f91STakashi Iwai  */
58771da177e4SLinus Torvalds 
5878352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5879352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5880352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5881352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5882fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5883352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
588483012a7cSTakashi Iwai #ifdef CONFIG_PM
5885fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5886cb53c626STakashi Iwai #endif
58871da177e4SLinus Torvalds };
58881da177e4SLinus Torvalds 
5889d8a766a1STakashi Iwai /*
5890dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
5891dda42bd0STakashi Iwai  * @codec: the HDA codec
5892dda42bd0STakashi Iwai  */
5893d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
58941da177e4SLinus Torvalds {
5895352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
58961da177e4SLinus Torvalds 	int err;
58971da177e4SLinus Torvalds 
5898e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5899352f7f91STakashi Iwai 	if (!spec)
59001da177e4SLinus Torvalds 		return -ENOMEM;
5901352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
59021da177e4SLinus Torvalds 	codec->spec = spec;
59031da177e4SLinus Torvalds 
59049eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
59059eb413e5STakashi Iwai 	if (err < 0)
59069eb413e5STakashi Iwai 		return err;
59079eb413e5STakashi Iwai 
59089eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5909352f7f91STakashi Iwai 	if (err < 0)
59101da177e4SLinus Torvalds 		goto error;
59111da177e4SLinus Torvalds 
59121da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
59131da177e4SLinus Torvalds 	return 0;
59141da177e4SLinus Torvalds 
59151da177e4SLinus Torvalds error:
5916fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
59171da177e4SLinus Torvalds 	return err;
59181da177e4SLinus Torvalds }
5919d8a766a1STakashi Iwai 
5920b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_generic[] = {
5921b9a94a9cSTakashi Iwai 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
5922d8a766a1STakashi Iwai 	{} /* terminator */
5923d8a766a1STakashi Iwai };
5924b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
5925d8a766a1STakashi Iwai 
5926d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
5927b9a94a9cSTakashi Iwai 	.id = snd_hda_id_generic,
5928d8a766a1STakashi Iwai };
5929d8a766a1STakashi Iwai 
5930d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
5931b21bdd0dSTakashi Iwai 
5932b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
5933b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
5934