xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 2ded3e5b)
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>
311da177e4SLinus Torvalds #include <sound/core.h>
32352f7f91STakashi Iwai #include <sound/jack.h>
331da177e4SLinus Torvalds #include "hda_codec.h"
341da177e4SLinus Torvalds #include "hda_local.h"
35352f7f91STakashi Iwai #include "hda_auto_parser.h"
36352f7f91STakashi Iwai #include "hda_jack.h"
377504b6cdSTakashi Iwai #include "hda_beep.h"
38352f7f91STakashi Iwai #include "hda_generic.h"
391da177e4SLinus Torvalds 
401da177e4SLinus Torvalds 
41352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
42352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
431da177e4SLinus Torvalds {
44352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
45352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
460186f4f4STakashi Iwai 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
4738cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
48352f7f91STakashi Iwai 	return 0;
49352f7f91STakashi Iwai }
50352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
511da177e4SLinus Torvalds 
5212c93df6STakashi Iwai struct snd_kcontrol_new *
5312c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
54352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
55352f7f91STakashi Iwai {
56352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
57352f7f91STakashi Iwai 	if (!knew)
58352f7f91STakashi Iwai 		return NULL;
59352f7f91STakashi Iwai 	*knew = *temp;
60352f7f91STakashi Iwai 	if (name)
61352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
62352f7f91STakashi Iwai 	else if (knew->name)
63352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
64352f7f91STakashi Iwai 	if (!knew->name)
65352f7f91STakashi Iwai 		return NULL;
66352f7f91STakashi Iwai 	return knew;
67352f7f91STakashi Iwai }
6812c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
69352f7f91STakashi Iwai 
70352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
71352f7f91STakashi Iwai {
72352f7f91STakashi Iwai 	if (spec->kctls.list) {
73352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
74352f7f91STakashi Iwai 		int i;
75352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
76352f7f91STakashi Iwai 			kfree(kctl[i].name);
77352f7f91STakashi Iwai 	}
78352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
79352f7f91STakashi Iwai }
80352f7f91STakashi Iwai 
81352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
82352f7f91STakashi Iwai {
831da177e4SLinus Torvalds 	if (!spec)
841da177e4SLinus Torvalds 		return;
85352f7f91STakashi Iwai 	free_kctls(spec);
86352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
870186f4f4STakashi Iwai 	snd_array_free(&spec->loopback_list);
881da177e4SLinus Torvalds }
89352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds /*
921c70a583STakashi Iwai  * store user hints
931c70a583STakashi Iwai  */
941c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
951c70a583STakashi Iwai {
961c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
971c70a583STakashi Iwai 	int val;
981c70a583STakashi Iwai 
991c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1001c70a583STakashi Iwai 	if (val >= 0)
1011c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1021c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1031c70a583STakashi Iwai 	if (val >= 0)
1041c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1051c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1061c70a583STakashi Iwai 	if (val >= 0)
1071c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1081c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1091c70a583STakashi Iwai 	if (val >= 0)
1101c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1111c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1121c70a583STakashi Iwai 	if (val >= 0)
1131c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1141c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1151c70a583STakashi Iwai 	if (val >= 0)
1161c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1171c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1181c70a583STakashi Iwai 	if (val >= 0)
1191c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1201c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1211c70a583STakashi Iwai 	if (val >= 0)
1221c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1231c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1241c70a583STakashi Iwai 	if (val >= 0)
1251c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
1261c70a583STakashi Iwai 
127f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
128f72706beSTakashi Iwai 	if (val >= 0)
129f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1301c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1311c70a583STakashi Iwai 	if (val >= 0)
1321c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1331c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1341c70a583STakashi Iwai 	if (val >= 0)
1351c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1367eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1377eebffd3STakashi Iwai 	if (val >= 0)
1387eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1391c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1401c70a583STakashi Iwai 	if (val >= 0)
1411c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1421c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1431c70a583STakashi Iwai 	if (val >= 0)
1441c70a583STakashi Iwai 		spec->no_primary_hp = !val;
145da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
146da96fb5bSTakashi Iwai 	if (val >= 0)
147da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1481c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1491c70a583STakashi Iwai 	if (val >= 0)
1501c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1511c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1521c70a583STakashi Iwai 	if (val >= 0)
1531c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1541c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1551c70a583STakashi Iwai 	if (val >= 0)
1561c70a583STakashi Iwai 		spec->indep_hp = !!val;
1571c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1581c70a583STakashi Iwai 	if (val >= 0)
1591c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
160f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1611c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1621c70a583STakashi Iwai 	if (val >= 0)
163f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
16429476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
16529476558STakashi Iwai 	if (val >= 0)
166f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
167f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
168f811c3cfSTakashi Iwai 	if (val >= 0)
169f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
17055196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
17155196fffSTakashi Iwai 	if (val >= 0)
17255196fffSTakashi Iwai 		spec->power_down_unused = !!val;
173967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
174967303daSTakashi Iwai 	if (val >= 0)
175967303daSTakashi Iwai 		spec->hp_mic = !!val;
176967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
177967303daSTakashi Iwai 	if (val >= 0)
178967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1791c70a583STakashi Iwai 
1801c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1811c70a583STakashi Iwai 		spec->mixer_nid = val;
1821c70a583STakashi Iwai }
1831c70a583STakashi Iwai 
1841c70a583STakashi Iwai /*
1852c12c30dSTakashi Iwai  * pin control value accesses
1862c12c30dSTakashi Iwai  */
1872c12c30dSTakashi Iwai 
1882c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
1892c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
1902c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
1912c12c30dSTakashi Iwai 
1922c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
1932c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
1942c12c30dSTakashi Iwai {
1952c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
1962c12c30dSTakashi Iwai }
1972c12c30dSTakashi Iwai 
1982c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
1992c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2002c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2012c12c30dSTakashi Iwai {
2022c12c30dSTakashi Iwai 	if (!pin)
2032c12c30dSTakashi Iwai 		return;
2042c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2052c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2062c12c30dSTakashi Iwai 	if (do_write)
2072c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2082c12c30dSTakashi Iwai }
2092c12c30dSTakashi Iwai 
2102c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2112c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2122c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2132c12c30dSTakashi Iwai {
2142c12c30dSTakashi Iwai 	int i;
2152c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2162c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2172c12c30dSTakashi Iwai }
2182c12c30dSTakashi Iwai 
2192c12c30dSTakashi Iwai /*
220352f7f91STakashi Iwai  * parsing paths
2211da177e4SLinus Torvalds  */
2221da177e4SLinus Torvalds 
2233ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2243ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2253ca529d3STakashi Iwai {
2263ca529d3STakashi Iwai 	int i;
2273ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2283ca529d3STakashi Iwai 		if (list[i] == nid)
2293ca529d3STakashi Iwai 			return i;
2303ca529d3STakashi Iwai 	return -1;
2313ca529d3STakashi Iwai }
2323ca529d3STakashi Iwai 
2333ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2343ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2353ca529d3STakashi Iwai {
2363ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2373ca529d3STakashi Iwai }
2383ca529d3STakashi Iwai 
239f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
240f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2413ca529d3STakashi Iwai 				     int anchor_nid)
2421da177e4SLinus Torvalds {
243352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
244352f7f91STakashi Iwai 	int i;
2451da177e4SLinus Torvalds 
246352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
247352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
248352f7f91STakashi Iwai 		if (path->depth <= 0)
249352f7f91STakashi Iwai 			continue;
250352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
251f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2523ca529d3STakashi Iwai 			if (!anchor_nid ||
2533ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2543ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
255352f7f91STakashi Iwai 				return path;
2561da177e4SLinus Torvalds 		}
257f5172a7eSTakashi Iwai 	}
2581da177e4SLinus Torvalds 	return NULL;
2591da177e4SLinus Torvalds }
260f5172a7eSTakashi Iwai 
261f5172a7eSTakashi Iwai /* get the path between the given NIDs;
262f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
263f5172a7eSTakashi Iwai  */
264f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
265f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
266f5172a7eSTakashi Iwai {
2673ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
268f5172a7eSTakashi Iwai }
269352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
2701da177e4SLinus Torvalds 
271196c1766STakashi Iwai /* get the index number corresponding to the path instance;
272196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
273196c1766STakashi Iwai  */
274196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
275196c1766STakashi Iwai {
276196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
277196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
278196c1766STakashi Iwai 	ssize_t idx;
279196c1766STakashi Iwai 
280196c1766STakashi Iwai 	if (!spec->paths.used)
281196c1766STakashi Iwai 		return 0;
282196c1766STakashi Iwai 	idx = path - array;
283196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
284196c1766STakashi Iwai 		return 0;
285196c1766STakashi Iwai 	return idx + 1;
286196c1766STakashi Iwai }
2874bd01e93STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_path_idx);
288196c1766STakashi Iwai 
289196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
290196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
291196c1766STakashi Iwai {
292196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
293196c1766STakashi Iwai 
294196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
295196c1766STakashi Iwai 		return NULL;
296196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
297196c1766STakashi Iwai }
2984bd01e93STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_path_from_idx);
299196c1766STakashi Iwai 
300352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
301352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3021da177e4SLinus Torvalds {
303352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
304352f7f91STakashi Iwai 	int i;
305352f7f91STakashi Iwai 
306352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
307352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
308352f7f91STakashi Iwai 		if (path->path[0] == nid)
309352f7f91STakashi Iwai 			return true;
310352f7f91STakashi Iwai 	}
311352f7f91STakashi Iwai 	return false;
3121da177e4SLinus Torvalds }
3131da177e4SLinus Torvalds 
314352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
315352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
316352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3171da177e4SLinus Torvalds {
318352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
319352f7f91STakashi Iwai 		return false;
320352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3211da177e4SLinus Torvalds }
3221da177e4SLinus Torvalds 
323352f7f91STakashi Iwai /* nid, dir and idx */
324352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
325352f7f91STakashi Iwai 
326352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
327352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3281da177e4SLinus Torvalds {
329352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
330352f7f91STakashi Iwai 	int i;
331352f7f91STakashi Iwai 
332352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
333352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
334352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
335352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
336352f7f91STakashi Iwai 			return true;
337352f7f91STakashi Iwai 	}
338352f7f91STakashi Iwai 	return false;
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
341352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
342352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3438999bf0aSTakashi Iwai 			      int dir, int idx, int type)
344cb53c626STakashi Iwai {
345352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3468999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
347cb53c626STakashi Iwai }
348352f7f91STakashi Iwai 
3490c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
3500c8c0f56STakashi Iwai {
3510c8c0f56STakashi Iwai 	char buf[40];
3520c8c0f56STakashi Iwai 	int i;
3530c8c0f56STakashi Iwai 
3540c8c0f56STakashi Iwai 
3550c8c0f56STakashi Iwai 	buf[0] = 0;
3560c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
3570c8c0f56STakashi Iwai 		char tmp[4];
3580c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
3590c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
3600c8c0f56STakashi Iwai 	}
3610c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
3620c8c0f56STakashi Iwai }
3630c8c0f56STakashi Iwai 
364352f7f91STakashi Iwai /* called recursively */
365352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
366352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3673ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3683ca529d3STakashi Iwai 			     int depth)
369352f7f91STakashi Iwai {
370ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
371352f7f91STakashi Iwai 	int i, nums;
372352f7f91STakashi Iwai 
3733ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3743ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3753ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3763ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
377352f7f91STakashi Iwai 
378ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
379352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
380352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
381352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
382352f7f91STakashi Iwai 			 * try to find an empty DAC
383352f7f91STakashi Iwai 			 */
384352f7f91STakashi Iwai 			if (from_nid ||
385352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
386352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
387352f7f91STakashi Iwai 				continue;
388352f7f91STakashi Iwai 		}
3893ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
3903ca529d3STakashi Iwai 		if (anchor_nid <= 0)
391352f7f91STakashi Iwai 			goto found;
392352f7f91STakashi Iwai 	}
393352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
394352f7f91STakashi Iwai 		return false;
395352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
396352f7f91STakashi Iwai 		unsigned int type;
397352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
398352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
399352f7f91STakashi Iwai 		    type == AC_WID_PIN)
400352f7f91STakashi Iwai 			continue;
401352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4023ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
403352f7f91STakashi Iwai 			goto found;
404352f7f91STakashi Iwai 	}
405352f7f91STakashi Iwai 	return false;
406352f7f91STakashi Iwai 
407352f7f91STakashi Iwai  found:
408352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
409352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
410352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
411352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
412352f7f91STakashi Iwai 	path->depth++;
413352f7f91STakashi Iwai 	return true;
414352f7f91STakashi Iwai }
415352f7f91STakashi Iwai 
416352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
417352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4183ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4193ca529d3STakashi Iwai  * with the given value are evaluated.
4203ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4213ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4223ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
423352f7f91STakashi Iwai  */
424352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4253ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
426352f7f91STakashi Iwai 			    struct nid_path *path)
427352f7f91STakashi Iwai {
4283ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
429352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
430352f7f91STakashi Iwai 		path->depth++;
431352f7f91STakashi Iwai 		return true;
432352f7f91STakashi Iwai 	}
433352f7f91STakashi Iwai 	return false;
434352f7f91STakashi Iwai }
435352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
436352f7f91STakashi Iwai 
437352f7f91STakashi Iwai /*
438352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
439352f7f91STakashi Iwai  * if no valid path is found, return NULL
440352f7f91STakashi Iwai  */
441352f7f91STakashi Iwai struct nid_path *
442352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4433ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
444352f7f91STakashi Iwai {
445352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
446352f7f91STakashi Iwai 	struct nid_path *path;
447352f7f91STakashi Iwai 
448352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
449352f7f91STakashi Iwai 		return NULL;
450352f7f91STakashi Iwai 
451f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4523ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
453f5172a7eSTakashi Iwai 	if (path)
454f5172a7eSTakashi Iwai 		return path;
455f5172a7eSTakashi Iwai 
456352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
457352f7f91STakashi Iwai 	if (!path)
458352f7f91STakashi Iwai 		return NULL;
459352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4603ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
461352f7f91STakashi Iwai 		return path;
462352f7f91STakashi Iwai 	/* push back */
463352f7f91STakashi Iwai 	spec->paths.used--;
464352f7f91STakashi Iwai 	return NULL;
465352f7f91STakashi Iwai }
466352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
467352f7f91STakashi Iwai 
468980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
469980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
470980428ceSTakashi Iwai {
471980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
472980428ceSTakashi Iwai 	if (!path)
473980428ceSTakashi Iwai 		return;
474980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
475980428ceSTakashi Iwai }
476980428ceSTakashi Iwai 
477352f7f91STakashi Iwai /* look for an empty DAC slot */
478352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
479352f7f91STakashi Iwai 			      bool is_digital)
480352f7f91STakashi Iwai {
481352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
482352f7f91STakashi Iwai 	bool cap_digital;
483352f7f91STakashi Iwai 	int i;
484352f7f91STakashi Iwai 
485352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
486352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
487352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
488352f7f91STakashi Iwai 			continue;
489352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
490352f7f91STakashi Iwai 		if (is_digital != cap_digital)
491352f7f91STakashi Iwai 			continue;
492352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
493352f7f91STakashi Iwai 			return nid;
494352f7f91STakashi Iwai 	}
495352f7f91STakashi Iwai 	return 0;
496352f7f91STakashi Iwai }
497352f7f91STakashi Iwai 
498352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
499352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
500352f7f91STakashi Iwai {
501352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
502352f7f91STakashi Iwai 	val |= chs << 16;
503352f7f91STakashi Iwai 	return val;
504352f7f91STakashi Iwai }
505352f7f91STakashi Iwai 
506352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
507352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
508352f7f91STakashi Iwai 			   int dir, unsigned int bits)
509352f7f91STakashi Iwai {
510352f7f91STakashi Iwai 	if (!nid)
511352f7f91STakashi Iwai 		return false;
512352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
513352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
514352f7f91STakashi Iwai 			return true;
515352f7f91STakashi Iwai 	return false;
516352f7f91STakashi Iwai }
517352f7f91STakashi Iwai 
51899a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
51999a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
52099a5592dSDavid Henningsson {
52199a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
52299a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
52399a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
52499a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
52599a5592dSDavid Henningsson }
52699a5592dSDavid Henningsson 
527352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
528f69910ddSTakashi Iwai 	check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
529352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
530352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
531352f7f91STakashi Iwai 
532352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
533352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
534352f7f91STakashi Iwai 				       struct nid_path *path)
535352f7f91STakashi Iwai {
536352f7f91STakashi Iwai 	int i;
537352f7f91STakashi Iwai 
538352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
539352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
540352f7f91STakashi Iwai 			return path->path[i];
541352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
542352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
543352f7f91STakashi Iwai 			return path->path[i];
544352f7f91STakashi Iwai 	}
545352f7f91STakashi Iwai 	return 0;
546352f7f91STakashi Iwai }
547352f7f91STakashi Iwai 
548352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
549352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
550352f7f91STakashi Iwai 				      struct nid_path *path)
551352f7f91STakashi Iwai {
552a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
553352f7f91STakashi Iwai 	int i;
554352f7f91STakashi Iwai 
555352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
556a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
557a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
558a1114a8cSTakashi Iwai 			continue;
559a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
560a1114a8cSTakashi Iwai 			return nid;
561352f7f91STakashi Iwai 	}
562352f7f91STakashi Iwai 	return 0;
563352f7f91STakashi Iwai }
564352f7f91STakashi Iwai 
565352f7f91STakashi Iwai /*
566352f7f91STakashi Iwai  * path activation / deactivation
567352f7f91STakashi Iwai  */
568352f7f91STakashi Iwai 
569352f7f91STakashi Iwai /* can have the amp-in capability? */
570352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
571352f7f91STakashi Iwai {
572352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
573352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
574352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
575352f7f91STakashi Iwai 
576352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
577352f7f91STakashi Iwai 		return false;
578352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
579352f7f91STakashi Iwai 		return false;
580352f7f91STakashi Iwai 	return true;
581352f7f91STakashi Iwai }
582352f7f91STakashi Iwai 
583352f7f91STakashi Iwai /* can have the amp-out capability? */
584352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
585352f7f91STakashi Iwai {
586352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
587352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
588352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
589352f7f91STakashi Iwai 
590352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
591352f7f91STakashi Iwai 		return false;
592352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
593352f7f91STakashi Iwai 		return false;
594352f7f91STakashi Iwai 	return true;
595352f7f91STakashi Iwai }
596352f7f91STakashi Iwai 
597352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
598352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
5997dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
600352f7f91STakashi Iwai {
601352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
602352f7f91STakashi Iwai 	int i, n;
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
605352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
606352f7f91STakashi Iwai 		if (!path->active)
607352f7f91STakashi Iwai 			continue;
608352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
609352f7f91STakashi Iwai 			if (path->path[i] == nid) {
610352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
611352f7f91STakashi Iwai 					return true;
612352f7f91STakashi Iwai 				break;
613352f7f91STakashi Iwai 			}
614352f7f91STakashi Iwai 		}
615352f7f91STakashi Iwai 	}
616352f7f91STakashi Iwai 	return false;
617352f7f91STakashi Iwai }
618352f7f91STakashi Iwai 
619b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
620b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
621b1b9fbd0STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, 0)
622b1b9fbd0STakashi Iwai 
623352f7f91STakashi Iwai /* get the default amp value for the target state */
624352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6258999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
626352f7f91STakashi Iwai {
627352f7f91STakashi Iwai 	unsigned int val = 0;
628352f7f91STakashi Iwai 
629352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
630352f7f91STakashi Iwai 		/* set to 0dB */
631352f7f91STakashi Iwai 		if (enable)
632352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
633352f7f91STakashi Iwai 	}
634f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
635352f7f91STakashi Iwai 		if (!enable)
636352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
637352f7f91STakashi Iwai 	}
638352f7f91STakashi Iwai 	return val;
639352f7f91STakashi Iwai }
640352f7f91STakashi Iwai 
641352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
642352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
643352f7f91STakashi Iwai {
6448999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6458999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
646352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
647352f7f91STakashi Iwai }
648352f7f91STakashi Iwai 
6498999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6508999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
6518999bf0aSTakashi Iwai  */
6528999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
6538999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
6548999bf0aSTakashi Iwai 					   unsigned int caps)
655352f7f91STakashi Iwai {
6568999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
6578999bf0aSTakashi Iwai 
658f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
6598999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
6608999bf0aSTakashi Iwai 			mask &= ~0x80;
6618999bf0aSTakashi Iwai 	}
6628999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
6638999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
6648999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
6658999bf0aSTakashi Iwai 			mask &= ~0x7f;
6668999bf0aSTakashi Iwai 	}
6678999bf0aSTakashi Iwai 	return mask;
6688999bf0aSTakashi Iwai }
6698999bf0aSTakashi Iwai 
6708999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
6718999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
6728999bf0aSTakashi Iwai {
6738999bf0aSTakashi Iwai 	unsigned int caps;
6748999bf0aSTakashi Iwai 	unsigned int mask, val;
6758999bf0aSTakashi Iwai 
6767dddf2aeSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
677352f7f91STakashi Iwai 		return;
6788999bf0aSTakashi Iwai 
6798999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
6808999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
6818999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
6828999bf0aSTakashi Iwai 	if (!mask)
6838999bf0aSTakashi Iwai 		return;
6848999bf0aSTakashi Iwai 
6858999bf0aSTakashi Iwai 	val &= mask;
6868999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
687352f7f91STakashi Iwai }
688352f7f91STakashi Iwai 
689352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
690352f7f91STakashi Iwai 			     int i, bool enable)
691352f7f91STakashi Iwai {
692352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
693352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
6948999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
695352f7f91STakashi Iwai }
696352f7f91STakashi Iwai 
697352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
698352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
699352f7f91STakashi Iwai {
700352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
701ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
702352f7f91STakashi Iwai 	int n, nums, idx;
703352f7f91STakashi Iwai 	int type;
704352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
705352f7f91STakashi Iwai 
706ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
707352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
708352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
709352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
710352f7f91STakashi Iwai 		nums = 1;
711352f7f91STakashi Iwai 		idx = 0;
712352f7f91STakashi Iwai 	} else
713352f7f91STakashi Iwai 		idx = path->idx[i];
714352f7f91STakashi Iwai 
715352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
716352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
717352f7f91STakashi Iwai 
718352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
719352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
720352f7f91STakashi Iwai 	 */
721352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
722e4a395e7STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
723352f7f91STakashi Iwai 			continue;
7248999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
725352f7f91STakashi Iwai 	}
726352f7f91STakashi Iwai }
727352f7f91STakashi Iwai 
728352f7f91STakashi Iwai /* activate or deactivate the given path
729352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
730352f7f91STakashi Iwai  */
731352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
732352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
733352f7f91STakashi Iwai {
73455196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
735352f7f91STakashi Iwai 	int i;
736352f7f91STakashi Iwai 
737352f7f91STakashi Iwai 	if (!enable)
738352f7f91STakashi Iwai 		path->active = false;
739352f7f91STakashi Iwai 
740352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
74155196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
74255196fffSTakashi Iwai 		if (enable && spec->power_down_unused) {
74355196fffSTakashi Iwai 			/* make sure the widget is powered up */
74455196fffSTakashi Iwai 			if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
74555196fffSTakashi Iwai 				snd_hda_codec_write(codec, nid, 0,
74655196fffSTakashi Iwai 						    AC_VERB_SET_POWER_STATE,
74755196fffSTakashi Iwai 						    AC_PWRST_D0);
74855196fffSTakashi Iwai 		}
749352f7f91STakashi Iwai 		if (enable && path->multi[i])
75055196fffSTakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
751352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
752352f7f91STakashi Iwai 					    path->idx[i]);
753352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
754352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
755352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
756352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
757352f7f91STakashi Iwai 	}
758352f7f91STakashi Iwai 
759352f7f91STakashi Iwai 	if (enable)
760352f7f91STakashi Iwai 		path->active = true;
761352f7f91STakashi Iwai }
762352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
763352f7f91STakashi Iwai 
76455196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
76555196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
76655196fffSTakashi Iwai {
76755196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
768868211dbSJiri Slaby 	bool changed = false;
76955196fffSTakashi Iwai 	int i;
77055196fffSTakashi Iwai 
77155196fffSTakashi Iwai 	if (!spec->power_down_unused || path->active)
77255196fffSTakashi Iwai 		return;
77355196fffSTakashi Iwai 
77455196fffSTakashi Iwai 	for (i = 0; i < path->depth; i++) {
77555196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
776b1b9fbd0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
777b1b9fbd0STakashi Iwai 		    !is_active_nid_for_any(codec, nid)) {
77855196fffSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
77955196fffSTakashi Iwai 					    AC_VERB_SET_POWER_STATE,
78055196fffSTakashi Iwai 					    AC_PWRST_D3);
78155196fffSTakashi Iwai 			changed = true;
78255196fffSTakashi Iwai 		}
78355196fffSTakashi Iwai 	}
78455196fffSTakashi Iwai 
78555196fffSTakashi Iwai 	if (changed) {
78655196fffSTakashi Iwai 		msleep(10);
78755196fffSTakashi Iwai 		snd_hda_codec_read(codec, path->path[0], 0,
78855196fffSTakashi Iwai 				   AC_VERB_GET_POWER_STATE, 0);
78955196fffSTakashi Iwai 	}
79055196fffSTakashi Iwai }
79155196fffSTakashi Iwai 
792d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
793d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
794d5a9f1bbSTakashi Iwai {
795d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
796d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
797d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
798d5a9f1bbSTakashi Iwai 		return;
79905909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
80005909d5cSTakashi Iwai 		return;
801468ac413STakashi Iwai 	if (codec->inv_eapd)
802468ac413STakashi Iwai 		enable = !enable;
803d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
804d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
805d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
806d5a9f1bbSTakashi Iwai }
807d5a9f1bbSTakashi Iwai 
8083e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
8093e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
8103e367f15STakashi Iwai {
8113e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
8123e367f15STakashi Iwai 	if (path)
8133e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
8143e367f15STakashi Iwai }
8153e367f15STakashi Iwai 
816352f7f91STakashi Iwai 
817352f7f91STakashi Iwai /*
818352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
819352f7f91STakashi Iwai  */
820352f7f91STakashi Iwai 
8217eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
8227eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
823bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
824bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
8257eebffd3STakashi Iwai 
826352f7f91STakashi Iwai enum {
827352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
828352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
829352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
830352f7f91STakashi Iwai };
831352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
832352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
8337eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
8347eebffd3STakashi Iwai 	{
8357eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8367eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
8377eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
8387eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
8397eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
8407eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
8417eebffd3STakashi Iwai 	},
842bc2eee29STakashi Iwai 	{
843bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
844bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
845bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
846bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
847bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
848bc2eee29STakashi Iwai 	},
849352f7f91STakashi Iwai };
850352f7f91STakashi Iwai 
851352f7f91STakashi Iwai /* add dynamic controls from template */
852a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
853a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
854352f7f91STakashi Iwai 		       int cidx, unsigned long val)
855352f7f91STakashi Iwai {
856352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
857352f7f91STakashi Iwai 
85812c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
859352f7f91STakashi Iwai 	if (!knew)
860a35bd1e3STakashi Iwai 		return NULL;
861352f7f91STakashi Iwai 	knew->index = cidx;
862352f7f91STakashi Iwai 	if (get_amp_nid_(val))
863352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
864352f7f91STakashi Iwai 	knew->private_value = val;
865a35bd1e3STakashi Iwai 	return knew;
866352f7f91STakashi Iwai }
867352f7f91STakashi Iwai 
868352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
869352f7f91STakashi Iwai 				const char *pfx, const char *dir,
870352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
871352f7f91STakashi Iwai {
872975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
873352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
874a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
875a35bd1e3STakashi Iwai 		return -ENOMEM;
876a35bd1e3STakashi Iwai 	return 0;
877352f7f91STakashi Iwai }
878352f7f91STakashi Iwai 
879352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
880352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
881352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
882352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
883352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
884352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
885352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
886352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
887352f7f91STakashi Iwai 
888352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
889352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
890352f7f91STakashi Iwai {
891352f7f91STakashi Iwai 	unsigned int val;
892352f7f91STakashi Iwai 	if (!path)
893352f7f91STakashi Iwai 		return 0;
894352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
895352f7f91STakashi Iwai 	if (!val)
896352f7f91STakashi Iwai 		return 0;
897352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
898352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
899352f7f91STakashi Iwai }
900352f7f91STakashi Iwai 
901352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
902352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
903352f7f91STakashi Iwai 			       int type)
904352f7f91STakashi Iwai {
905352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
906352f7f91STakashi Iwai 	if (path) {
907352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
908352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
909352f7f91STakashi Iwai 			chs = 3; /* stereo */
910352f7f91STakashi Iwai 	}
911352f7f91STakashi Iwai 	return chs;
912352f7f91STakashi Iwai }
913352f7f91STakashi Iwai 
914352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
915352f7f91STakashi Iwai 			  struct nid_path *path)
916352f7f91STakashi Iwai {
917352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
918352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
919352f7f91STakashi Iwai }
920352f7f91STakashi Iwai 
921352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
922352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
923352f7f91STakashi Iwai  */
924352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
925352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
926352f7f91STakashi Iwai {
927352f7f91STakashi Iwai 	unsigned int val;
928352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
929352f7f91STakashi Iwai 
930352f7f91STakashi Iwai 	if (!path)
931352f7f91STakashi Iwai 		return 0;
932352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
933352f7f91STakashi Iwai 	if (!val)
934352f7f91STakashi Iwai 		return 0;
935352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
936352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
937352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
938352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
939352f7f91STakashi Iwai 		if (nums > 1) {
940352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
941352f7f91STakashi Iwai 			val |= nums << 19;
942352f7f91STakashi Iwai 		}
943352f7f91STakashi Iwai 	}
944352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
945352f7f91STakashi Iwai }
946352f7f91STakashi Iwai 
947352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
948352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
949352f7f91STakashi Iwai {
950352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
951352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
952352f7f91STakashi Iwai }
953352f7f91STakashi Iwai 
9547eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
955bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
9567eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
9577eebffd3STakashi Iwai {
9587eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9597eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
9607eebffd3STakashi Iwai 
9617eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
9627eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
9637eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
9647eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
9657eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
9667eebffd3STakashi Iwai 	}
967bc2eee29STakashi Iwai }
9687eebffd3STakashi Iwai 
969bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
970bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
971bc2eee29STakashi Iwai {
972bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
9737eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
9747eebffd3STakashi Iwai }
9757eebffd3STakashi Iwai 
976bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
977bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
978bc2eee29STakashi Iwai {
979bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
980bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
981bc2eee29STakashi Iwai }
982bc2eee29STakashi Iwai 
983247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
984247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
985247d85eeSTakashi Iwai {
986247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
987247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
988247d85eeSTakashi Iwai }
989247d85eeSTakashi Iwai 
990352f7f91STakashi Iwai static const char * const channel_name[4] = {
991352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
992352f7f91STakashi Iwai };
993352f7f91STakashi Iwai 
994352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
995247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
996247d85eeSTakashi Iwai 				    int *index, int ctl_type)
997352f7f91STakashi Iwai {
998247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
999352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1000352f7f91STakashi Iwai 
1001352f7f91STakashi Iwai 	*index = 0;
1002352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1003247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1004352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1005352f7f91STakashi Iwai 
1006352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1007352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1008352f7f91STakashi Iwai 	 */
1009352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1010352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1011352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1012352f7f91STakashi Iwai 
1013247d85eeSTakashi Iwai 	/* multi-io channels */
1014247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1015247d85eeSTakashi Iwai 		return channel_name[ch];
1016247d85eeSTakashi Iwai 
1017352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1018352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1019247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1020247d85eeSTakashi Iwai 		 * don't name it as Speaker
1021247d85eeSTakashi Iwai 		 */
1022247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1023247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1024247d85eeSTakashi Iwai 			break;
1025352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1026352f7f91STakashi Iwai 			return "Speaker";
1027352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1028352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1029352f7f91STakashi Iwai 		break;
1030352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1031247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1032247d85eeSTakashi Iwai 		 * don't name it as Headphone
1033247d85eeSTakashi Iwai 		 */
1034247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1035247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1036247d85eeSTakashi Iwai 			break;
1037352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1038352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1039352f7f91STakashi Iwai 			break;
1040352f7f91STakashi Iwai 		*index = ch;
1041352f7f91STakashi Iwai 		return "Headphone";
1042247d85eeSTakashi Iwai 	}
1043247d85eeSTakashi Iwai 
1044247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1045352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
1046352f7f91STakashi Iwai 		return "PCM";
1047247d85eeSTakashi Iwai 
1048352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1049352f7f91STakashi Iwai 		snd_BUG();
1050352f7f91STakashi Iwai 		return "PCM";
1051352f7f91STakashi Iwai 	}
1052352f7f91STakashi Iwai 
1053352f7f91STakashi Iwai 	return channel_name[ch];
1054352f7f91STakashi Iwai }
1055352f7f91STakashi Iwai 
1056352f7f91STakashi Iwai /*
1057352f7f91STakashi Iwai  * Parse output paths
1058352f7f91STakashi Iwai  */
1059352f7f91STakashi Iwai 
1060352f7f91STakashi Iwai /* badness definition */
1061352f7f91STakashi Iwai enum {
1062352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1063352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1064352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1065352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1066352f7f91STakashi Iwai 	/* No possible multi-ios */
10671d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1068352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1069352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1070352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1071352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1072352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1073352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
107455a63d4dSTakashi Iwai 	/* No independent HP possible */
1075bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1076352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1077352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1078352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1079352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1080352f7f91STakashi Iwai 	/* Volume widget is shared */
1081352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1082352f7f91STakashi Iwai };
1083352f7f91STakashi Iwai 
10840e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1085352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1086352f7f91STakashi Iwai  *
1087352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1088352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1089352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1090352f7f91STakashi Iwai  */
10910e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1092352f7f91STakashi Iwai {
1093352f7f91STakashi Iwai 	hda_nid_t nid;
1094352f7f91STakashi Iwai 	unsigned int val;
1095352f7f91STakashi Iwai 	int badness = 0;
1096352f7f91STakashi Iwai 
1097352f7f91STakashi Iwai 	if (!path)
1098352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
10990e614dd0STakashi Iwai 
11000e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
11010e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
11020e614dd0STakashi Iwai 		return 0; /* already evaluated */
11030e614dd0STakashi Iwai 
1104352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1105352f7f91STakashi Iwai 	if (nid) {
1106352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1107352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1108352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1109352f7f91STakashi Iwai 		else
1110352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1111352f7f91STakashi Iwai 	} else
1112352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1113352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1114352f7f91STakashi Iwai 	if (nid) {
1115352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1116352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1117352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1118352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1119352f7f91STakashi Iwai 		else
1120352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1121352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1122352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1123352f7f91STakashi Iwai 		else
1124352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1125352f7f91STakashi Iwai 	} else
1126352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1127352f7f91STakashi Iwai 	return badness;
1128352f7f91STakashi Iwai }
1129352f7f91STakashi Iwai 
113098bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1131352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1132352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1133352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1134352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1135352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1136352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1137352f7f91STakashi Iwai };
113898bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_main_out_badness);
1139352f7f91STakashi Iwai 
114098bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1141352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1142352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1143352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1144352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1145352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1146352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1147352f7f91STakashi Iwai };
114898bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_extra_out_badness);
1149352f7f91STakashi Iwai 
11507385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
11517385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
11527385df61STakashi Iwai {
11537385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
11547385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
11557385df61STakashi Iwai 
11567385df61STakashi Iwai 	if (cfg->line_outs > idx)
11577385df61STakashi Iwai 		return spec->private_dac_nids[idx];
11587385df61STakashi Iwai 	idx -= cfg->line_outs;
11597385df61STakashi Iwai 	if (spec->multi_ios > idx)
11607385df61STakashi Iwai 		return spec->multi_io[idx].dac;
11617385df61STakashi Iwai 	return 0;
11627385df61STakashi Iwai }
11637385df61STakashi Iwai 
11647385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
11657385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
11667385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
11677385df61STakashi Iwai {
11687385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
11697385df61STakashi Iwai }
11707385df61STakashi Iwai 
1171352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1172352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1173352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1174196c1766STakashi Iwai 			   int *path_idx,
1175352f7f91STakashi Iwai 			   const struct badness_table *bad)
1176352f7f91STakashi Iwai {
1177352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1178352f7f91STakashi Iwai 	int i, j;
1179352f7f91STakashi Iwai 	int badness = 0;
1180352f7f91STakashi Iwai 	hda_nid_t dac;
1181352f7f91STakashi Iwai 
1182352f7f91STakashi Iwai 	if (!num_outs)
1183352f7f91STakashi Iwai 		return 0;
1184352f7f91STakashi Iwai 
1185352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
11860c8c0f56STakashi Iwai 		struct nid_path *path;
1187352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
11881e0b5286STakashi Iwai 
11890e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
11900e614dd0STakashi Iwai 		if (path) {
11910e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
11921e0b5286STakashi Iwai 			continue;
11931e0b5286STakashi Iwai 		}
11941e0b5286STakashi Iwai 
1195352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1196352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1197980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1198352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1199352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1200352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1201352f7f91STakashi Iwai 					dacs[j] = 0;
1202980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1203196c1766STakashi Iwai 					path_idx[j] = 0;
1204352f7f91STakashi Iwai 					break;
1205352f7f91STakashi Iwai 				}
1206352f7f91STakashi Iwai 			}
1207352f7f91STakashi Iwai 		}
1208352f7f91STakashi Iwai 		dac = dacs[i];
1209352f7f91STakashi Iwai 		if (!dac) {
12107385df61STakashi Iwai 			if (num_outs > 2)
12117385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
12127385df61STakashi Iwai 			if (!dac)
12137385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
12147385df61STakashi Iwai 			if (!dac)
12157385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1216352f7f91STakashi Iwai 			if (dac) {
1217352f7f91STakashi Iwai 				if (!i)
1218352f7f91STakashi Iwai 					badness += bad->shared_primary;
1219352f7f91STakashi Iwai 				else if (i == 1)
1220352f7f91STakashi Iwai 					badness += bad->shared_surr;
1221352f7f91STakashi Iwai 				else
1222352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1223352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1224352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1225352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1226352f7f91STakashi Iwai 			} else if (!i)
1227352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1228352f7f91STakashi Iwai 			else
1229352f7f91STakashi Iwai 				badness += bad->no_dac;
1230352f7f91STakashi Iwai 		}
12311fa335b0STakashi Iwai 		if (!dac)
12321fa335b0STakashi Iwai 			continue;
12333ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1234117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1235b3a8c745STakashi Iwai 			/* try with aamix */
12363ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1237b3a8c745STakashi Iwai 		}
12381fa335b0STakashi Iwai 		if (!path) {
1239352f7f91STakashi Iwai 			dac = dacs[i] = 0;
12401fa335b0STakashi Iwai 			badness += bad->no_dac;
12411fa335b0STakashi Iwai 		} else {
1242a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1243e1284af7STakashi Iwai 			path->active = true;
1244196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
12450e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1246e1284af7STakashi Iwai 		}
1247352f7f91STakashi Iwai 	}
1248352f7f91STakashi Iwai 
1249352f7f91STakashi Iwai 	return badness;
1250352f7f91STakashi Iwai }
1251352f7f91STakashi Iwai 
1252352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1253352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1254352f7f91STakashi Iwai {
1255352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1256352f7f91STakashi Iwai 	int i;
1257352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1258352f7f91STakashi Iwai 
1259352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1260352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1261352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1262352f7f91STakashi Iwai 			continue;
1263352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1264352f7f91STakashi Iwai 			if (nid_found)
1265352f7f91STakashi Iwai 				return 0;
1266352f7f91STakashi Iwai 			nid_found = nid;
1267352f7f91STakashi Iwai 		}
1268352f7f91STakashi Iwai 	}
1269352f7f91STakashi Iwai 	return nid_found;
1270352f7f91STakashi Iwai }
1271352f7f91STakashi Iwai 
1272352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1273352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1274352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1275352f7f91STakashi Iwai {
1276352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1277352f7f91STakashi Iwai 
1278352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1279352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1280352f7f91STakashi Iwai 		return false;
1281352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1282352f7f91STakashi Iwai 		return false;
1283352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1284352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1285352f7f91STakashi Iwai 		return false;
1286352f7f91STakashi Iwai 	return true;
1287352f7f91STakashi Iwai }
1288352f7f91STakashi Iwai 
1289e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1290e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1291e22aab7dSTakashi Iwai {
1292e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1293e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1294e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1295e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1296e22aab7dSTakashi Iwai 	int type, i;
1297e22aab7dSTakashi Iwai 	int num_pins = 0;
1298e22aab7dSTakashi Iwai 
1299e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1300e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1301e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1302e22aab7dSTakashi Iwai 				continue;
1303e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1304e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1305e22aab7dSTakashi Iwai 				num_pins++;
1306e22aab7dSTakashi Iwai 		}
1307e22aab7dSTakashi Iwai 	}
1308e22aab7dSTakashi Iwai 	return num_pins;
1309e22aab7dSTakashi Iwai }
1310e22aab7dSTakashi Iwai 
1311352f7f91STakashi Iwai /*
1312352f7f91STakashi Iwai  * multi-io helper
1313352f7f91STakashi Iwai  *
1314352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1315352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1316352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1317352f7f91STakashi Iwai  * the badness value.
1318352f7f91STakashi Iwai  */
1319352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1320352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1321e22aab7dSTakashi Iwai 			  bool hardwired)
1322352f7f91STakashi Iwai {
1323352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1324352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1325e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1326352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1327352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1328352f7f91STakashi Iwai 	int badness = 0;
13290e614dd0STakashi Iwai 	struct nid_path *path;
1330352f7f91STakashi Iwai 
1331352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1332352f7f91STakashi Iwai 	if (old_pins >= 2)
1333352f7f91STakashi Iwai 		goto end_fill;
1334352f7f91STakashi Iwai 
1335e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1336352f7f91STakashi Iwai 	if (num_pins < 2)
1337352f7f91STakashi Iwai 		goto end_fill;
1338352f7f91STakashi Iwai 
1339352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1340352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1341352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1342352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1343352f7f91STakashi Iwai 
1344352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1345352f7f91STakashi Iwai 				continue;
1346352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1347352f7f91STakashi Iwai 				continue;
1348352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1349352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1350352f7f91STakashi Iwai 					break;
1351352f7f91STakashi Iwai 			}
1352352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1353352f7f91STakashi Iwai 				continue;
1354352f7f91STakashi Iwai 
1355352f7f91STakashi Iwai 			if (hardwired)
1356352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1357352f7f91STakashi Iwai 			else if (!dac)
1358352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1359352f7f91STakashi Iwai 			if (!dac) {
1360352f7f91STakashi Iwai 				badness++;
1361352f7f91STakashi Iwai 				continue;
1362352f7f91STakashi Iwai 			}
13633ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
13643ca529d3STakashi Iwai 						    -spec->mixer_nid);
13650c8c0f56STakashi Iwai 			if (!path) {
1366352f7f91STakashi Iwai 				badness++;
1367352f7f91STakashi Iwai 				continue;
1368352f7f91STakashi Iwai 			}
1369a769409cSTakashi Iwai 			/* print_nid_path("multiio", path); */
1370352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1371352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1372196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1373196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1374352f7f91STakashi Iwai 			spec->multi_ios++;
1375352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1376352f7f91STakashi Iwai 				break;
1377352f7f91STakashi Iwai 		}
1378352f7f91STakashi Iwai 	}
1379352f7f91STakashi Iwai  end_fill:
1380352f7f91STakashi Iwai 	if (badness)
1381352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1382352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1383352f7f91STakashi Iwai 		if (hardwired)
1384352f7f91STakashi Iwai 			return 1; /* nothing found */
1385352f7f91STakashi Iwai 		else
1386352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1387352f7f91STakashi Iwai 	}
1388352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1389352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1390352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1391352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1392352f7f91STakashi Iwai 		return badness;
1393352f7f91STakashi Iwai 	}
1394352f7f91STakashi Iwai 
1395352f7f91STakashi Iwai 	/* assign volume and mute controls */
13960e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
13970e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
13980e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
13990e614dd0STakashi Iwai 	}
1400352f7f91STakashi Iwai 
1401352f7f91STakashi Iwai 	return badness;
1402352f7f91STakashi Iwai }
1403352f7f91STakashi Iwai 
1404352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1405352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1406196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1407352f7f91STakashi Iwai {
1408b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1409352f7f91STakashi Iwai 	int i;
1410352f7f91STakashi Iwai 	bool found = false;
1411352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
14120c8c0f56STakashi Iwai 		struct nid_path *path;
1413352f7f91STakashi Iwai 		hda_nid_t dac;
1414352f7f91STakashi Iwai 		if (dacs[i])
1415352f7f91STakashi Iwai 			continue;
1416352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1417352f7f91STakashi Iwai 		if (!dac)
1418352f7f91STakashi Iwai 			continue;
14193ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
14203ca529d3STakashi Iwai 					    -spec->mixer_nid);
1421117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
14223ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
14230c8c0f56STakashi Iwai 		if (path) {
1424352f7f91STakashi Iwai 			dacs[i] = dac;
1425352f7f91STakashi Iwai 			found = true;
1426a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1427e1284af7STakashi Iwai 			path->active = true;
1428196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1429352f7f91STakashi Iwai 		}
1430352f7f91STakashi Iwai 	}
1431352f7f91STakashi Iwai 	return found;
1432352f7f91STakashi Iwai }
1433352f7f91STakashi Iwai 
1434c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1435c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1436c30aa7b2STakashi Iwai {
14373ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1438c30aa7b2STakashi Iwai 	struct nid_path *path;
14395ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1440c30aa7b2STakashi Iwai 
1441c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
14423ca529d3STakashi Iwai 	if (!path || !path->depth ||
14433ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1444c30aa7b2STakashi Iwai 		return 0;
14455ead56f2STakashi Iwai 	path_dac = path->path[0];
14465ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1447f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1448f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1449f87498b6STakashi Iwai 	if (!path) {
14505ead56f2STakashi Iwai 		if (dac != path_dac)
14515ead56f2STakashi Iwai 			dac = path_dac;
1452f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1453f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1454f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1455f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
14565ead56f2STakashi Iwai 		else
14575ead56f2STakashi Iwai 			dac = 0;
1458f87498b6STakashi Iwai 		if (dac)
1459f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
14603ca529d3STakashi Iwai 						    spec->mixer_nid);
1461f87498b6STakashi Iwai 	}
1462c30aa7b2STakashi Iwai 	if (!path)
1463c30aa7b2STakashi Iwai 		return 0;
1464a769409cSTakashi Iwai 	/* print_nid_path("output-aamix", path); */
1465c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1466c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1467c30aa7b2STakashi Iwai }
1468c30aa7b2STakashi Iwai 
146955a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
147055a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
147155a63d4dSTakashi Iwai {
147255a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
147355a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
147455a63d4dSTakashi Iwai 	struct nid_path *path;
147555a63d4dSTakashi Iwai 	int i, idx;
147655a63d4dSTakashi Iwai 
147755a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
147855a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
147955a63d4dSTakashi Iwai 	else
148055a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
148155a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
148255a63d4dSTakashi Iwai 	if (!path)
148355a63d4dSTakashi Iwai 		return false;
148455a63d4dSTakashi Iwai 
148555a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
148655a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
148755a63d4dSTakashi Iwai 		return true;
148855a63d4dSTakashi Iwai 
148955a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
149055a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
149155a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
149255a63d4dSTakashi Iwai 			break;
149355a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
149455a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
149555a63d4dSTakashi Iwai 			return false;
149655a63d4dSTakashi Iwai 	}
149755a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
149855a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
149955a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
150055a63d4dSTakashi Iwai 			return false;
150155a63d4dSTakashi Iwai 	}
150255a63d4dSTakashi Iwai 
150355a63d4dSTakashi Iwai 	return true;
150455a63d4dSTakashi Iwai }
150555a63d4dSTakashi Iwai 
1506a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1507a07a949bSTakashi Iwai  * shared dac pointed by the paths
1508a07a949bSTakashi Iwai  */
1509a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1510a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1511a07a949bSTakashi Iwai {
1512a07a949bSTakashi Iwai 	struct nid_path *path;
1513a07a949bSTakashi Iwai 	int i;
1514a07a949bSTakashi Iwai 
1515a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1516a07a949bSTakashi Iwai 		if (dacs[i])
1517a07a949bSTakashi Iwai 			continue;
1518a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1519a07a949bSTakashi Iwai 		if (!path)
1520a07a949bSTakashi Iwai 			continue;
1521a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1522a07a949bSTakashi Iwai 	}
1523a07a949bSTakashi Iwai }
1524a07a949bSTakashi Iwai 
1525352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1526352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1527352f7f91STakashi Iwai 			      bool fill_hardwired,
1528352f7f91STakashi Iwai 			      bool fill_mio_first)
1529352f7f91STakashi Iwai {
1530352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1531352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1532352f7f91STakashi Iwai 	int i, err, badness;
1533352f7f91STakashi Iwai 
1534352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1535352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1536352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1537352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1538352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1539352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1540352f7f91STakashi Iwai 	spec->multi_ios = 0;
1541352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1542cd5be3f9STakashi Iwai 
1543cd5be3f9STakashi Iwai 	/* clear path indices */
1544cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1545cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1546cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1547cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1548cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1549c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1550cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1551cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1552cd5be3f9STakashi Iwai 
1553352f7f91STakashi Iwai 	badness = 0;
1554352f7f91STakashi Iwai 
1555352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1556352f7f91STakashi Iwai 	if (fill_hardwired) {
1557352f7f91STakashi Iwai 		bool mapped;
1558352f7f91STakashi Iwai 		do {
1559352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1560352f7f91STakashi Iwai 					     cfg->line_out_pins,
1561196c1766STakashi Iwai 					     spec->private_dac_nids,
1562196c1766STakashi Iwai 					     spec->out_paths);
1563352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1564352f7f91STakashi Iwai 					      cfg->hp_pins,
1565196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1566196c1766STakashi Iwai 					      spec->hp_paths);
1567352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1568352f7f91STakashi Iwai 					      cfg->speaker_pins,
1569196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1570196c1766STakashi Iwai 					      spec->speaker_paths);
1571da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1572da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1573352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1574e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1575352f7f91STakashi Iwai 				if (!err)
1576352f7f91STakashi Iwai 					mapped = true;
1577352f7f91STakashi Iwai 			}
1578352f7f91STakashi Iwai 		} while (mapped);
1579352f7f91STakashi Iwai 	}
1580352f7f91STakashi Iwai 
1581352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1582196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
158398bd1115STakashi Iwai 				   spec->main_out_badness);
1584352f7f91STakashi Iwai 
1585da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1586352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1587352f7f91STakashi Iwai 		/* try to fill multi-io first */
1588e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1589352f7f91STakashi Iwai 		if (err < 0)
1590352f7f91STakashi Iwai 			return err;
1591352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1592352f7f91STakashi Iwai 	}
1593352f7f91STakashi Iwai 
1594352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1595352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1596352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1597196c1766STakashi Iwai 				      spec->hp_paths,
159898bd1115STakashi Iwai 				      spec->extra_out_badness);
1599352f7f91STakashi Iwai 		if (err < 0)
1600352f7f91STakashi Iwai 			return err;
1601352f7f91STakashi Iwai 		badness += err;
1602352f7f91STakashi Iwai 	}
1603352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1604352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1605352f7f91STakashi Iwai 				      cfg->speaker_pins,
1606352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1607196c1766STakashi Iwai 				      spec->speaker_paths,
160898bd1115STakashi Iwai 				      spec->extra_out_badness);
1609352f7f91STakashi Iwai 		if (err < 0)
1610352f7f91STakashi Iwai 			return err;
1611352f7f91STakashi Iwai 		badness += err;
1612352f7f91STakashi Iwai 	}
1613da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1614da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1615e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1616352f7f91STakashi Iwai 		if (err < 0)
1617352f7f91STakashi Iwai 			return err;
1618352f7f91STakashi Iwai 		badness += err;
1619352f7f91STakashi Iwai 	}
1620e22aab7dSTakashi Iwai 
1621c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1622c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1623c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1624c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1625c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1626c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1627c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1628c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1629c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1630c30aa7b2STakashi Iwai 	}
1631c30aa7b2STakashi Iwai 
1632da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1633da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1634e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1635e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1636352f7f91STakashi Iwai 
1637a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1638a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1639a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1640a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1641a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1642a07a949bSTakashi Iwai 		else {
1643a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1644a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1645a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1646a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1647a07a949bSTakashi Iwai 		}
1648a07a949bSTakashi Iwai 	}
1649a07a949bSTakashi Iwai 
1650a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1651c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1652a07a949bSTakashi Iwai 
1653352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1654352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1655352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1656352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1657352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1658352f7f91STakashi Iwai 		spec->multi_ios = 0;
1659352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1660352f7f91STakashi Iwai 	}
1661352f7f91STakashi Iwai 
166255a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
166355a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
166455a63d4dSTakashi Iwai 
1665a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1666a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1667a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1668a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1669a07a949bSTakashi Iwai 				   spec->hp_paths);
1670a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1671a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1672a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1673a07a949bSTakashi Iwai 				   spec->speaker_paths);
1674a07a949bSTakashi Iwai 
1675352f7f91STakashi Iwai 	return badness;
1676352f7f91STakashi Iwai }
1677352f7f91STakashi Iwai 
1678352f7f91STakashi Iwai #define DEBUG_BADNESS
1679352f7f91STakashi Iwai 
1680352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1681352f7f91STakashi Iwai #define debug_badness	snd_printdd
1682352f7f91STakashi Iwai #else
1683352f7f91STakashi Iwai #define debug_badness(...)
1684352f7f91STakashi Iwai #endif
1685352f7f91STakashi Iwai 
1686a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1687a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1688a769409cSTakashi Iwai 				      const char *pfx, int idx)
1689352f7f91STakashi Iwai {
1690a769409cSTakashi Iwai 	struct nid_path *path;
1691a769409cSTakashi Iwai 
1692a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1693a769409cSTakashi Iwai 	if (path)
1694a769409cSTakashi Iwai 		print_nid_path(pfx, path);
1695a769409cSTakashi Iwai }
1696a769409cSTakashi Iwai 
1697a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1698a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1699a769409cSTakashi Iwai {
1700a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1701a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1702a769409cSTakashi Iwai 	int i;
1703a769409cSTakashi Iwai 
1704a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1705352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1706708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1707352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1708352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1709352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1710a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1711a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1712a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1713a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1714352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1715352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1716352f7f91STakashi Iwai 			      spec->multi_ios,
1717352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1718352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1719a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1720a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1721a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1722a769409cSTakashi Iwai 	if (cfg->hp_outs)
1723352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1724352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1725708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1726352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1727352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1728352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1729352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1730a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1731a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1732a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1733352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1734352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1735352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1736352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1737352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1738352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1739352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1740a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1741a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1742a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1743a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1744352f7f91STakashi Iwai }
1745a769409cSTakashi Iwai #else
1746a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1747a769409cSTakashi Iwai #endif
1748352f7f91STakashi Iwai 
1749352f7f91STakashi Iwai /* find all available DACs of the codec */
1750352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1751352f7f91STakashi Iwai {
1752352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1753352f7f91STakashi Iwai 	int i;
1754352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1755352f7f91STakashi Iwai 
1756352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1757352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1758352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1759352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1760352f7f91STakashi Iwai 			continue;
1761352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1762352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1763352f7f91STakashi Iwai 			break;
1764352f7f91STakashi Iwai 		}
1765352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1766352f7f91STakashi Iwai 	}
1767352f7f91STakashi Iwai }
1768352f7f91STakashi Iwai 
1769352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1770352f7f91STakashi Iwai {
1771352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1772352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1773352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
17749314a581STakashi Iwai 	unsigned int val;
1775352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1776352f7f91STakashi Iwai 	int badness;
1777352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1778352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1779352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1780352f7f91STakashi Iwai 
1781352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1782352f7f91STakashi Iwai 	if (!best_cfg)
1783352f7f91STakashi Iwai 		return -ENOMEM;
1784352f7f91STakashi Iwai 	*best_cfg = *cfg;
1785352f7f91STakashi Iwai 
1786352f7f91STakashi Iwai 	for (;;) {
1787352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1788352f7f91STakashi Iwai 					     fill_mio_first);
1789352f7f91STakashi Iwai 		if (badness < 0) {
1790352f7f91STakashi Iwai 			kfree(best_cfg);
1791352f7f91STakashi Iwai 			return badness;
1792352f7f91STakashi Iwai 		}
1793352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1794352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1795352f7f91STakashi Iwai 			      badness);
1796a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1797352f7f91STakashi Iwai 		if (badness < best_badness) {
1798352f7f91STakashi Iwai 			best_badness = badness;
1799352f7f91STakashi Iwai 			*best_cfg = *cfg;
1800352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1801352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1802352f7f91STakashi Iwai 		}
1803352f7f91STakashi Iwai 		if (!badness)
1804352f7f91STakashi Iwai 			break;
1805352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1806352f7f91STakashi Iwai 		if (!fill_mio_first)
1807352f7f91STakashi Iwai 			continue;
1808352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1809352f7f91STakashi Iwai 		if (!fill_hardwired)
1810352f7f91STakashi Iwai 			continue;
1811352f7f91STakashi Iwai 		if (hp_spk_swapped)
1812352f7f91STakashi Iwai 			break;
1813352f7f91STakashi Iwai 		hp_spk_swapped = true;
1814352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1815352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1816352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1817352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1818352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1819352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1820352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1821352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1822352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1823352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1824352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1825352f7f91STakashi Iwai 			fill_hardwired = true;
1826352f7f91STakashi Iwai 			continue;
1827352f7f91STakashi Iwai 		}
1828352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1829352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1830352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1831352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1832352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1833352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1834352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1835352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1836352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1837352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1838352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1839352f7f91STakashi Iwai 			fill_hardwired = true;
1840352f7f91STakashi Iwai 			continue;
1841352f7f91STakashi Iwai 		}
1842352f7f91STakashi Iwai 		break;
1843352f7f91STakashi Iwai 	}
1844352f7f91STakashi Iwai 
1845352f7f91STakashi Iwai 	if (badness) {
18460c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1847352f7f91STakashi Iwai 		*cfg = *best_cfg;
1848352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1849352f7f91STakashi Iwai 	}
1850352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1851352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1852a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
1853352f7f91STakashi Iwai 
1854352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1855352f7f91STakashi Iwai 		struct nid_path *path;
1856196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1857352f7f91STakashi Iwai 		if (path)
1858352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
18597a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
18607a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
18617a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1862352f7f91STakashi Iwai 	}
1863352f7f91STakashi Iwai 
18649314a581STakashi Iwai 	/* set initial pinctl targets */
18659314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
18669314a581STakashi Iwai 		val = PIN_HP;
18679314a581STakashi Iwai 	else
18689314a581STakashi Iwai 		val = PIN_OUT;
18699314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
18709314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
18719314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
18729314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
18739314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
18749314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
18759314a581STakashi Iwai 				cfg->speaker_pins, val);
18769314a581STakashi Iwai 	}
18779314a581STakashi Iwai 
187855a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
187955a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
188055a63d4dSTakashi Iwai 		spec->indep_hp = 0;
188155a63d4dSTakashi Iwai 
1882352f7f91STakashi Iwai 	kfree(best_cfg);
1883352f7f91STakashi Iwai 	return 0;
1884352f7f91STakashi Iwai }
1885352f7f91STakashi Iwai 
1886352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1887352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1888352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1889352f7f91STakashi Iwai {
1890352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1891352f7f91STakashi Iwai 	int i, err, noutputs;
1892352f7f91STakashi Iwai 
1893352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1894352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1895352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1896352f7f91STakashi Iwai 
1897352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1898352f7f91STakashi Iwai 		const char *name;
1899352f7f91STakashi Iwai 		int index;
1900352f7f91STakashi Iwai 		struct nid_path *path;
1901352f7f91STakashi Iwai 
1902196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1903352f7f91STakashi Iwai 		if (!path)
1904352f7f91STakashi Iwai 			continue;
1905247d85eeSTakashi Iwai 
1906247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1907352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1908352f7f91STakashi Iwai 			/* Center/LFE */
1909352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1910352f7f91STakashi Iwai 			if (err < 0)
1911352f7f91STakashi Iwai 				return err;
1912352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1913352f7f91STakashi Iwai 			if (err < 0)
1914352f7f91STakashi Iwai 				return err;
1915247d85eeSTakashi Iwai 		} else {
1916247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1917247d85eeSTakashi Iwai 			if (err < 0)
1918247d85eeSTakashi Iwai 				return err;
1919247d85eeSTakashi Iwai 		}
1920247d85eeSTakashi Iwai 
1921247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1922247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1923352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1924352f7f91STakashi Iwai 			if (err < 0)
1925352f7f91STakashi Iwai 				return err;
1926352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1927352f7f91STakashi Iwai 			if (err < 0)
1928352f7f91STakashi Iwai 				return err;
1929352f7f91STakashi Iwai 		} else {
1930352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1931352f7f91STakashi Iwai 			if (err < 0)
1932352f7f91STakashi Iwai 				return err;
1933352f7f91STakashi Iwai 		}
1934352f7f91STakashi Iwai 	}
1935352f7f91STakashi Iwai 	return 0;
1936352f7f91STakashi Iwai }
1937352f7f91STakashi Iwai 
1938c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1939196c1766STakashi Iwai 			    const char *pfx, int cidx)
1940352f7f91STakashi Iwai {
1941352f7f91STakashi Iwai 	struct nid_path *path;
1942352f7f91STakashi Iwai 	int err;
1943352f7f91STakashi Iwai 
1944196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1945352f7f91STakashi Iwai 	if (!path)
1946352f7f91STakashi Iwai 		return 0;
1947352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1948352f7f91STakashi Iwai 	if (err < 0)
1949352f7f91STakashi Iwai 		return err;
1950352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1951352f7f91STakashi Iwai 	if (err < 0)
1952352f7f91STakashi Iwai 		return err;
1953352f7f91STakashi Iwai 	return 0;
1954352f7f91STakashi Iwai }
1955352f7f91STakashi Iwai 
1956352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1957352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1958196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1959352f7f91STakashi Iwai {
1960c2c80383STakashi Iwai 	int i;
1961352f7f91STakashi Iwai 
1962352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1963c2c80383STakashi Iwai 		const char *name;
1964975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1965c2c80383STakashi Iwai 		int err, idx = 0;
1966c2c80383STakashi Iwai 
1967c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1968c2c80383STakashi Iwai 			name = "Bass Speaker";
1969c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1970c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1971352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1972c2c80383STakashi Iwai 			name = tmp;
1973352f7f91STakashi Iwai 		} else {
1974c2c80383STakashi Iwai 			name = pfx;
1975c2c80383STakashi Iwai 			idx = i;
1976352f7f91STakashi Iwai 		}
1977c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1978352f7f91STakashi Iwai 		if (err < 0)
1979352f7f91STakashi Iwai 			return err;
1980352f7f91STakashi Iwai 	}
1981352f7f91STakashi Iwai 	return 0;
1982352f7f91STakashi Iwai }
1983352f7f91STakashi Iwai 
1984352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1985352f7f91STakashi Iwai {
1986352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1987352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1988196c1766STakashi Iwai 				 spec->hp_paths,
1989352f7f91STakashi Iwai 				 "Headphone");
1990352f7f91STakashi Iwai }
1991352f7f91STakashi Iwai 
1992352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1993352f7f91STakashi Iwai {
1994352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1995352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1996196c1766STakashi Iwai 				 spec->speaker_paths,
1997352f7f91STakashi Iwai 				 "Speaker");
1998352f7f91STakashi Iwai }
1999352f7f91STakashi Iwai 
2000352f7f91STakashi Iwai /*
200138cf6f1aSTakashi Iwai  * independent HP controls
200238cf6f1aSTakashi Iwai  */
200338cf6f1aSTakashi Iwai 
2004963afde9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
200538cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
200638cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
200738cf6f1aSTakashi Iwai {
200838cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
200938cf6f1aSTakashi Iwai }
201038cf6f1aSTakashi Iwai 
201138cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
201238cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
201338cf6f1aSTakashi Iwai {
201438cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
201538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
201638cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
201738cf6f1aSTakashi Iwai 	return 0;
201838cf6f1aSTakashi Iwai }
201938cf6f1aSTakashi Iwai 
2020a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2021a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2022a1e908edSTakashi Iwai 			       int out_type);
2023a1e908edSTakashi Iwai 
202438cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
202538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
202638cf6f1aSTakashi Iwai {
202738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
202838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
202938cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
203038cf6f1aSTakashi Iwai 	int ret = 0;
203138cf6f1aSTakashi Iwai 
203238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
203338cf6f1aSTakashi Iwai 	if (spec->active_streams) {
203438cf6f1aSTakashi Iwai 		ret = -EBUSY;
203538cf6f1aSTakashi Iwai 		goto unlock;
203638cf6f1aSTakashi Iwai 	}
203738cf6f1aSTakashi Iwai 
203838cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2039a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2040a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2041a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2042a1e908edSTakashi Iwai 		else
2043a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2044a1e908edSTakashi Iwai 
2045a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2046a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2047a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2048a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2049a1e908edSTakashi Iwai 						   spec->out_paths[0],
2050a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2051a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2052a1e908edSTakashi Iwai 			else
2053a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2054a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2055a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2056a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2057a1e908edSTakashi Iwai 		}
2058a1e908edSTakashi Iwai 
205938cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
206038cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2061a1e908edSTakashi Iwai 			*dacp = 0;
206238cf6f1aSTakashi Iwai 		else
2063a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
206492603c59STakashi Iwai 
2065963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
206638cf6f1aSTakashi Iwai 		ret = 1;
206738cf6f1aSTakashi Iwai 	}
206838cf6f1aSTakashi Iwai  unlock:
206938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
207038cf6f1aSTakashi Iwai 	return ret;
207138cf6f1aSTakashi Iwai }
207238cf6f1aSTakashi Iwai 
207338cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
207438cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
207538cf6f1aSTakashi Iwai 	.name = "Independent HP",
207638cf6f1aSTakashi Iwai 	.info = indep_hp_info,
207738cf6f1aSTakashi Iwai 	.get = indep_hp_get,
207838cf6f1aSTakashi Iwai 	.put = indep_hp_put,
207938cf6f1aSTakashi Iwai };
208038cf6f1aSTakashi Iwai 
208138cf6f1aSTakashi Iwai 
208238cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
208338cf6f1aSTakashi Iwai {
208438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2085a1e908edSTakashi Iwai 	hda_nid_t dac;
208638cf6f1aSTakashi Iwai 
208738cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
208838cf6f1aSTakashi Iwai 		return 0;
2089a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2090a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2091a1e908edSTakashi Iwai 	else
2092a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2093a1e908edSTakashi Iwai 	if (!dac) {
209438cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
209538cf6f1aSTakashi Iwai 		return 0;
209638cf6f1aSTakashi Iwai 	}
209738cf6f1aSTakashi Iwai 
209838cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2099a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
210038cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
210138cf6f1aSTakashi Iwai 		return -ENOMEM;
210238cf6f1aSTakashi Iwai 	return 0;
210338cf6f1aSTakashi Iwai }
210438cf6f1aSTakashi Iwai 
210538cf6f1aSTakashi Iwai /*
2106352f7f91STakashi Iwai  * channel mode enum control
2107352f7f91STakashi Iwai  */
2108352f7f91STakashi Iwai 
2109352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2110352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2111352f7f91STakashi Iwai {
2112352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2113352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2114a07a949bSTakashi Iwai 	int chs;
2115352f7f91STakashi Iwai 
2116352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2117352f7f91STakashi Iwai 	uinfo->count = 1;
2118352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2119352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2120352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2121a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2122a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2123352f7f91STakashi Iwai 	return 0;
2124352f7f91STakashi Iwai }
2125352f7f91STakashi Iwai 
2126352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2127352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2128352f7f91STakashi Iwai {
2129352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2130352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2131a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2132a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2133352f7f91STakashi Iwai 	return 0;
2134352f7f91STakashi Iwai }
2135352f7f91STakashi Iwai 
2136196c1766STakashi Iwai static inline struct nid_path *
2137196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2138196c1766STakashi Iwai {
2139196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2140196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2141196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2142196c1766STakashi Iwai }
2143196c1766STakashi Iwai 
2144a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2145a5cc2509STakashi Iwai 
214665033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
214765033cc8STakashi Iwai  * used for output paths
214865033cc8STakashi Iwai  */
214965033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
215065033cc8STakashi Iwai {
215165033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
215265033cc8STakashi Iwai }
215365033cc8STakashi Iwai 
2154352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2155352f7f91STakashi Iwai {
2156352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2157352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2158352f7f91STakashi Iwai 	struct nid_path *path;
2159352f7f91STakashi Iwai 
2160196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2161352f7f91STakashi Iwai 	if (!path)
2162352f7f91STakashi Iwai 		return -EINVAL;
2163352f7f91STakashi Iwai 
2164352f7f91STakashi Iwai 	if (path->active == output)
2165352f7f91STakashi Iwai 		return 0;
2166352f7f91STakashi Iwai 
2167352f7f91STakashi Iwai 	if (output) {
21682c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
216965033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2170d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2171352f7f91STakashi Iwai 	} else {
2172d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
217365033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
21742c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
217555196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2176352f7f91STakashi Iwai 	}
2177a365fed9STakashi Iwai 
2178a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2179a5cc2509STakashi Iwai 	update_automute_all(codec);
2180a365fed9STakashi Iwai 
2181352f7f91STakashi Iwai 	return 0;
2182352f7f91STakashi Iwai }
2183352f7f91STakashi Iwai 
2184352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2185352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2186352f7f91STakashi Iwai {
2187352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2188352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2189352f7f91STakashi Iwai 	int i, ch;
2190352f7f91STakashi Iwai 
2191352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2192352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2193352f7f91STakashi Iwai 		return -EINVAL;
2194a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2195352f7f91STakashi Iwai 		return 0;
2196a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2197352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2198352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2199352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2200352f7f91STakashi Iwai 					  spec->const_channel_count);
2201352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2202352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2203352f7f91STakashi Iwai 	return 1;
2204352f7f91STakashi Iwai }
2205352f7f91STakashi Iwai 
2206352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2207352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2208352f7f91STakashi Iwai 	.name = "Channel Mode",
2209352f7f91STakashi Iwai 	.info = ch_mode_info,
2210352f7f91STakashi Iwai 	.get = ch_mode_get,
2211352f7f91STakashi Iwai 	.put = ch_mode_put,
2212352f7f91STakashi Iwai };
2213352f7f91STakashi Iwai 
2214352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2215352f7f91STakashi Iwai {
2216352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2217352f7f91STakashi Iwai 
2218352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
221912c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2220352f7f91STakashi Iwai 			return -ENOMEM;
2221352f7f91STakashi Iwai 	}
2222352f7f91STakashi Iwai 	return 0;
2223352f7f91STakashi Iwai }
2224352f7f91STakashi Iwai 
2225352f7f91STakashi Iwai /*
2226c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2227c30aa7b2STakashi Iwai  */
2228c30aa7b2STakashi Iwai 
2229c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2230c30aa7b2STakashi Iwai 
2231c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2232c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2233c30aa7b2STakashi Iwai {
2234c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2235c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2236c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2237c30aa7b2STakashi Iwai 	return 0;
2238c30aa7b2STakashi Iwai }
2239c30aa7b2STakashi Iwai 
2240c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2241a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2242a1e908edSTakashi Iwai 			       int out_type)
2243c30aa7b2STakashi Iwai {
2244a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2245c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2246c30aa7b2STakashi Iwai 
2247c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2248c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2249c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2250c30aa7b2STakashi Iwai 		return;
2251a1e908edSTakashi Iwai 
2252a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2253a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2254a1e908edSTakashi Iwai 	 */
2255a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2256a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2257a1e908edSTakashi Iwai 		do_mix = false;
2258a1e908edSTakashi Iwai 
2259c30aa7b2STakashi Iwai 	if (do_mix) {
2260c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2261c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
226255196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2263c30aa7b2STakashi Iwai 	} else {
226465033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
226565033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
226655196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2267c30aa7b2STakashi Iwai 	}
2268c30aa7b2STakashi Iwai }
2269c30aa7b2STakashi Iwai 
2270c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2271c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2272c30aa7b2STakashi Iwai {
2273c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2274c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2275c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2276c30aa7b2STakashi Iwai 
2277c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2278c30aa7b2STakashi Iwai 		return 0;
2279c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2280c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2281a1e908edSTakashi Iwai 			   spec->aamix_out_paths[0],
2282a1e908edSTakashi Iwai 			   spec->autocfg.line_out_type);
2283c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2284a1e908edSTakashi Iwai 			   spec->aamix_out_paths[1],
2285a1e908edSTakashi Iwai 			   AUTO_PIN_HP_OUT);
2286c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2287a1e908edSTakashi Iwai 			   spec->aamix_out_paths[2],
2288a1e908edSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
2289c30aa7b2STakashi Iwai 	return 1;
2290c30aa7b2STakashi Iwai }
2291c30aa7b2STakashi Iwai 
2292c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2293c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2294c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2295c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2296c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2297c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2298c30aa7b2STakashi Iwai };
2299c30aa7b2STakashi Iwai 
2300c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2301c30aa7b2STakashi Iwai {
2302c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2303c30aa7b2STakashi Iwai 
2304c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2305c30aa7b2STakashi Iwai 		return 0;
2306c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2307c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2308c30aa7b2STakashi Iwai 		return 0;
2309c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2310c30aa7b2STakashi Iwai 		return -ENOMEM;
2311a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2312c30aa7b2STakashi Iwai 	return 0;
2313c30aa7b2STakashi Iwai }
2314c30aa7b2STakashi Iwai 
2315c30aa7b2STakashi Iwai /*
2316352f7f91STakashi Iwai  * shared headphone/mic handling
2317352f7f91STakashi Iwai  */
2318352f7f91STakashi Iwai 
2319352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2320352f7f91STakashi Iwai 
2321352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2322967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2323352f7f91STakashi Iwai {
2324352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2325967303daSTakashi Iwai 	bool as_mic;
2326352f7f91STakashi Iwai 	unsigned int val;
2327967303daSTakashi Iwai 	hda_nid_t pin;
2328967303daSTakashi Iwai 
2329967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2330967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2331967303daSTakashi Iwai 
2332967303daSTakashi Iwai 	if (!force) {
2333967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2334967303daSTakashi Iwai 		if (as_mic) {
2335967303daSTakashi Iwai 			if (val & PIN_IN)
2336967303daSTakashi Iwai 				return;
2337967303daSTakashi Iwai 		} else {
2338967303daSTakashi Iwai 			if (val & PIN_OUT)
2339967303daSTakashi Iwai 				return;
2340967303daSTakashi Iwai 		}
2341967303daSTakashi Iwai 	}
2342352f7f91STakashi Iwai 
2343352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2344967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2345967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2346967303daSTakashi Iwai 	 */
2347352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2348352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2349352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2350352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
23517594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2352967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2353352f7f91STakashi Iwai 	}
2354352f7f91STakashi Iwai 
23558ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2356967303daSTakashi Iwai 		if (as_mic)
2357967303daSTakashi Iwai 			val |= PIN_IN;
2358967303daSTakashi Iwai 		else
2359967303daSTakashi Iwai 			val = PIN_HP;
23602c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2361963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
23628ba955ceSTakashi Iwai 	}
2363352f7f91STakashi Iwai }
2364352f7f91STakashi Iwai 
2365352f7f91STakashi Iwai /* create a shared input with the headphone out */
2366967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2367352f7f91STakashi Iwai {
2368352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2369352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2370352f7f91STakashi Iwai 	unsigned int defcfg;
2371352f7f91STakashi Iwai 	hda_nid_t nid;
2372352f7f91STakashi Iwai 
2373967303daSTakashi Iwai 	if (!spec->hp_mic) {
2374967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2375352f7f91STakashi Iwai 			return 0;
2376967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2377967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2378967303daSTakashi Iwai 		 */
2379967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2380967303daSTakashi Iwai 			return 0;
2381967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2382352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2383352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2384352f7f91STakashi Iwai 				return 0;
2385967303daSTakashi Iwai 		}
2386967303daSTakashi Iwai 	}
2387352f7f91STakashi Iwai 
2388967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2389967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2390967303daSTakashi Iwai 		return 0;
2391967303daSTakashi Iwai 
2392967303daSTakashi Iwai 	nid = 0;
2393967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2394967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2395967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2396967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2397967303daSTakashi Iwai 	if (!nid)
2398967303daSTakashi Iwai 		return 0;
2399352f7f91STakashi Iwai 
2400352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2401352f7f91STakashi Iwai 		return 0; /* no input */
2402352f7f91STakashi Iwai 
2403967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2404967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2405cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2406967303daSTakashi Iwai 	cfg->num_inputs++;
2407967303daSTakashi Iwai 	spec->hp_mic = 1;
2408967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2409967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2410967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
2411352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2412352f7f91STakashi Iwai 	return 0;
2413352f7f91STakashi Iwai }
2414352f7f91STakashi Iwai 
2415978e77e7STakashi Iwai /*
2416978e77e7STakashi Iwai  * output jack mode
2417978e77e7STakashi Iwai  */
24185f171baaSTakashi Iwai 
24195f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
24205f171baaSTakashi Iwai 
24215f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
24225f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
24235f171baaSTakashi Iwai };
24245f171baaSTakashi Iwai 
2425978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2426978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2427978e77e7STakashi Iwai {
24285f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2429978e77e7STakashi Iwai }
2430978e77e7STakashi Iwai 
2431978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2432978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2433978e77e7STakashi Iwai {
2434978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2435978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2436978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2437978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2438978e77e7STakashi Iwai 	else
2439978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2440978e77e7STakashi Iwai 	return 0;
2441978e77e7STakashi Iwai }
2442978e77e7STakashi Iwai 
2443978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2444978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2445978e77e7STakashi Iwai {
2446978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2447978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2448978e77e7STakashi Iwai 	unsigned int val;
2449978e77e7STakashi Iwai 
2450978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2451978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2452978e77e7STakashi Iwai 		return 0;
2453978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2454978e77e7STakashi Iwai 	return 1;
2455978e77e7STakashi Iwai }
2456978e77e7STakashi Iwai 
2457978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2458978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2459978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2460978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2461978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2462978e77e7STakashi Iwai };
2463978e77e7STakashi Iwai 
2464978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2465978e77e7STakashi Iwai {
2466978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2467978e77e7STakashi Iwai 	int i;
2468978e77e7STakashi Iwai 
2469978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2470978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2471978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2472978e77e7STakashi Iwai 			return true;
2473978e77e7STakashi Iwai 	}
2474978e77e7STakashi Iwai 	return false;
2475978e77e7STakashi Iwai }
2476978e77e7STakashi Iwai 
2477978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2478978e77e7STakashi Iwai 			       char *name, size_t name_len)
2479978e77e7STakashi Iwai {
2480978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2481978e77e7STakashi Iwai 	int idx = 0;
2482978e77e7STakashi Iwai 
2483978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2484978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2485978e77e7STakashi Iwai 
2486978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2487978e77e7STakashi Iwai 		;
2488978e77e7STakashi Iwai }
2489978e77e7STakashi Iwai 
24905f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
24915f171baaSTakashi Iwai {
24925f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2493f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
24945f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
24955f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
24965f171baaSTakashi Iwai 			return 2;
24975f171baaSTakashi Iwai 	}
24985f171baaSTakashi Iwai 	return 1;
24995f171baaSTakashi Iwai }
25005f171baaSTakashi Iwai 
2501978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2502978e77e7STakashi Iwai 				 hda_nid_t *pins)
2503978e77e7STakashi Iwai {
2504978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2505978e77e7STakashi Iwai 	int i;
2506978e77e7STakashi Iwai 
2507978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2508978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2509ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
25105f171baaSTakashi Iwai 			continue;
25115f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2512978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2513975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2514978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2515978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2516978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2517978e77e7STakashi Iwai 			if (!knew)
2518978e77e7STakashi Iwai 				return -ENOMEM;
2519978e77e7STakashi Iwai 			knew->private_value = pin;
2520978e77e7STakashi Iwai 		}
2521978e77e7STakashi Iwai 	}
2522978e77e7STakashi Iwai 
2523978e77e7STakashi Iwai 	return 0;
2524978e77e7STakashi Iwai }
2525978e77e7STakashi Iwai 
252629476558STakashi Iwai /*
252729476558STakashi Iwai  * input jack mode
252829476558STakashi Iwai  */
252929476558STakashi Iwai 
253029476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
253129476558STakashi Iwai #define NUM_VREFS	6
253229476558STakashi Iwai 
253329476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
253429476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
253529476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
253629476558STakashi Iwai };
253729476558STakashi Iwai 
253829476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
253929476558STakashi Iwai {
254029476558STakashi Iwai 	unsigned int pincap;
254129476558STakashi Iwai 
254229476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
254329476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
254429476558STakashi Iwai 	/* filter out unusual vrefs */
254529476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
254629476558STakashi Iwai 	return pincap;
254729476558STakashi Iwai }
254829476558STakashi Iwai 
254929476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
255029476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
255129476558STakashi Iwai {
255229476558STakashi Iwai 	unsigned int i, n = 0;
255329476558STakashi Iwai 
255429476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
255529476558STakashi Iwai 		if (vref_caps & (1 << i)) {
255629476558STakashi Iwai 			if (n == item_idx)
255729476558STakashi Iwai 				return i;
255829476558STakashi Iwai 			n++;
255929476558STakashi Iwai 		}
256029476558STakashi Iwai 	}
256129476558STakashi Iwai 	return 0;
256229476558STakashi Iwai }
256329476558STakashi Iwai 
256429476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
256529476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
256629476558STakashi Iwai {
256729476558STakashi Iwai 	unsigned int i, n = 0;
256829476558STakashi Iwai 
256929476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
257029476558STakashi Iwai 		if (i == idx)
257129476558STakashi Iwai 			return n;
257229476558STakashi Iwai 		if (vref_caps & (1 << i))
257329476558STakashi Iwai 			n++;
257429476558STakashi Iwai 	}
257529476558STakashi Iwai 	return 0;
257629476558STakashi Iwai }
257729476558STakashi Iwai 
257829476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
257929476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
258029476558STakashi Iwai {
258129476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
258229476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
258329476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
258429476558STakashi Iwai 
258529476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
258629476558STakashi Iwai 				 vref_texts);
258729476558STakashi Iwai 	/* set the right text */
258829476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
258929476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
259029476558STakashi Iwai 	return 0;
259129476558STakashi Iwai }
259229476558STakashi Iwai 
259329476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
259429476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
259529476558STakashi Iwai {
259629476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
259729476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
259829476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
259929476558STakashi Iwai 	unsigned int idx;
260029476558STakashi Iwai 
260129476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
260229476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
260329476558STakashi Iwai 	return 0;
260429476558STakashi Iwai }
260529476558STakashi Iwai 
260629476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
260729476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
260829476558STakashi Iwai {
260929476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
261029476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
261129476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
261229476558STakashi Iwai 	unsigned int val, idx;
261329476558STakashi Iwai 
261429476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
261529476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
261629476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
261729476558STakashi Iwai 		return 0;
261829476558STakashi Iwai 
261929476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
262029476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
262129476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
262229476558STakashi Iwai 	return 1;
262329476558STakashi Iwai }
262429476558STakashi Iwai 
262529476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
262629476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
262729476558STakashi Iwai 	.info = in_jack_mode_info,
262829476558STakashi Iwai 	.get = in_jack_mode_get,
262929476558STakashi Iwai 	.put = in_jack_mode_put,
263029476558STakashi Iwai };
263129476558STakashi Iwai 
26325f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26335f171baaSTakashi Iwai {
26345f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
26355f171baaSTakashi Iwai 	int nitems = 0;
2636f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
26375f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
26385f171baaSTakashi Iwai 	return nitems ? nitems : 1;
26395f171baaSTakashi Iwai }
26405f171baaSTakashi Iwai 
264129476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
264229476558STakashi Iwai {
264329476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
264429476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2645975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
26465f171baaSTakashi Iwai 	unsigned int defcfg;
26475f171baaSTakashi Iwai 
2648f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2649f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
265029476558STakashi Iwai 
265129476558STakashi Iwai 	/* no jack mode for fixed pins */
265229476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
265329476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
265429476558STakashi Iwai 		return 0;
265529476558STakashi Iwai 
265629476558STakashi Iwai 	/* no multiple vref caps? */
26575f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
265829476558STakashi Iwai 		return 0;
265929476558STakashi Iwai 
266029476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
266129476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
266229476558STakashi Iwai 	if (!knew)
266329476558STakashi Iwai 		return -ENOMEM;
266429476558STakashi Iwai 	knew->private_value = pin;
266529476558STakashi Iwai 	return 0;
266629476558STakashi Iwai }
266729476558STakashi Iwai 
26685f171baaSTakashi Iwai /*
26695f171baaSTakashi Iwai  * HP/mic shared jack mode
26705f171baaSTakashi Iwai  */
26715f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
26725f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
26735f171baaSTakashi Iwai {
26745f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26755f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
26765f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
26775f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
26785f171baaSTakashi Iwai 	const char *text = NULL;
26795f171baaSTakashi Iwai 	int idx;
26805f171baaSTakashi Iwai 
26815f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
26825f171baaSTakashi Iwai 	uinfo->count = 1;
26835f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
26845f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
26855f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
26865f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
26875f171baaSTakashi Iwai 	if (idx < out_jacks) {
26885f171baaSTakashi Iwai 		if (out_jacks > 1)
26895f171baaSTakashi Iwai 			text = out_jack_texts[idx];
26905f171baaSTakashi Iwai 		else
26915f171baaSTakashi Iwai 			text = "Headphone Out";
26925f171baaSTakashi Iwai 	} else {
26935f171baaSTakashi Iwai 		idx -= out_jacks;
26945f171baaSTakashi Iwai 		if (in_jacks > 1) {
26955f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
26965f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
26975f171baaSTakashi Iwai 		} else
26985f171baaSTakashi Iwai 			text = "Mic In";
26995f171baaSTakashi Iwai 	}
27005f171baaSTakashi Iwai 
27015f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
27025f171baaSTakashi Iwai 	return 0;
27035f171baaSTakashi Iwai }
27045f171baaSTakashi Iwai 
27055f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
27065f171baaSTakashi Iwai {
27075f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27085f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27095f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
27105f171baaSTakashi Iwai 	int idx = 0;
27115f171baaSTakashi Iwai 
27125f171baaSTakashi Iwai 	if (val & PIN_OUT) {
27135f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
27145f171baaSTakashi Iwai 			idx = 1;
27155f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
27165f171baaSTakashi Iwai 		idx = out_jacks;
27175f171baaSTakashi Iwai 		if (in_jacks > 1) {
27185f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27195f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
27205f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
27215f171baaSTakashi Iwai 		}
27225f171baaSTakashi Iwai 	}
27235f171baaSTakashi Iwai 	return idx;
27245f171baaSTakashi Iwai }
27255f171baaSTakashi Iwai 
27265f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
27275f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27285f171baaSTakashi Iwai {
27295f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27305f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27315f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
27325f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
27335f171baaSTakashi Iwai 	return 0;
27345f171baaSTakashi Iwai }
27355f171baaSTakashi Iwai 
27365f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
27375f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27385f171baaSTakashi Iwai {
27395f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27405f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27415f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27425f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27435f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
27445f171baaSTakashi Iwai 
27455f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
27465f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
27475f171baaSTakashi Iwai 	if (oldval == idx)
27485f171baaSTakashi Iwai 		return 0;
27495f171baaSTakashi Iwai 
27505f171baaSTakashi Iwai 	if (idx < out_jacks) {
27515f171baaSTakashi Iwai 		if (out_jacks > 1)
27525f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
27535f171baaSTakashi Iwai 		else
27545f171baaSTakashi Iwai 			val = PIN_HP;
27555f171baaSTakashi Iwai 	} else {
27565f171baaSTakashi Iwai 		idx -= out_jacks;
27575f171baaSTakashi Iwai 		if (in_jacks > 1) {
27585f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27595f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
27603f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
27613f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
27625f171baaSTakashi Iwai 		} else
276316c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
27645f171baaSTakashi Iwai 	}
27655f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2766963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
27678ba955ceSTakashi Iwai 
27685f171baaSTakashi Iwai 	return 1;
27695f171baaSTakashi Iwai }
27705f171baaSTakashi Iwai 
27715f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
27725f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
27735f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
27745f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
27755f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
27765f171baaSTakashi Iwai };
27775f171baaSTakashi Iwai 
27785f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
27795f171baaSTakashi Iwai {
27805f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
27815f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
27825f171baaSTakashi Iwai 
27835f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
27845f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
27855f171baaSTakashi Iwai 	if (!knew)
27865f171baaSTakashi Iwai 		return -ENOMEM;
27875f171baaSTakashi Iwai 	knew->private_value = pin;
27888ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
27895f171baaSTakashi Iwai 	return 0;
27905f171baaSTakashi Iwai }
2791352f7f91STakashi Iwai 
2792352f7f91STakashi Iwai /*
2793352f7f91STakashi Iwai  * Parse input paths
2794352f7f91STakashi Iwai  */
2795352f7f91STakashi Iwai 
2796352f7f91STakashi Iwai /* add the powersave loopback-list entry */
27970186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2798352f7f91STakashi Iwai {
2799352f7f91STakashi Iwai 	struct hda_amp_list *list;
2800352f7f91STakashi Iwai 
28010186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
28020186f4f4STakashi Iwai 	if (!list)
28030186f4f4STakashi Iwai 		return -ENOMEM;
2804352f7f91STakashi Iwai 	list->nid = mix;
2805352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2806352f7f91STakashi Iwai 	list->idx = idx;
28070186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
28080186f4f4STakashi Iwai 	return 0;
2809cb53c626STakashi Iwai }
2810cb53c626STakashi Iwai 
2811*2ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
2812*2ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
2813*2ded3e5bSTakashi Iwai  */
2814*2ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
2815*2ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
2816*2ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
2817*2ded3e5bSTakashi Iwai {
2818*2ded3e5bSTakashi Iwai 	int idx, num_conns;
2819*2ded3e5bSTakashi Iwai 	const hda_nid_t *list;
2820*2ded3e5bSTakashi Iwai 	hda_nid_t nid;
2821*2ded3e5bSTakashi Iwai 
2822*2ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
2823*2ded3e5bSTakashi Iwai 	if (idx < 0)
2824*2ded3e5bSTakashi Iwai 		return false;
2825*2ded3e5bSTakashi Iwai 
2826*2ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
2827*2ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
2828*2ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2829*2ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
2830*2ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2831*2ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
2832*2ded3e5bSTakashi Iwai 		return true;
2833*2ded3e5bSTakashi Iwai 
2834*2ded3e5bSTakashi Iwai 	/* check leaf node */
2835*2ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
2836*2ded3e5bSTakashi Iwai 	if (num_conns < idx)
2837*2ded3e5bSTakashi Iwai 		return false;
2838*2ded3e5bSTakashi Iwai 	nid = list[idx];
2839*2ded3e5bSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
2840*2ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2841*2ded3e5bSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
2842*2ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2843*2ded3e5bSTakashi Iwai 
2844*2ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
2845*2ded3e5bSTakashi Iwai }
2846*2ded3e5bSTakashi Iwai 
2847352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2848196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2849196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2850352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
28511da177e4SLinus Torvalds {
2852352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2853352f7f91STakashi Iwai 	struct nid_path *path;
2854*2ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
2855352f7f91STakashi Iwai 	int err, idx;
28561da177e4SLinus Torvalds 
2857*2ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
2858*2ded3e5bSTakashi Iwai 		return 0;
2859352f7f91STakashi Iwai 
28603ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2861352f7f91STakashi Iwai 	if (!path)
2862352f7f91STakashi Iwai 		return -EINVAL;
28630c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2864196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2865352f7f91STakashi Iwai 
2866352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
2867*2ded3e5bSTakashi Iwai 	if (mix_val) {
2868*2ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
2869d13bd412STakashi Iwai 		if (err < 0)
28701da177e4SLinus Torvalds 			return err;
2871*2ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
28721da177e4SLinus Torvalds 	}
28731da177e4SLinus Torvalds 
2874*2ded3e5bSTakashi Iwai 	if (mute_val) {
2875*2ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
2876d13bd412STakashi Iwai 		if (err < 0)
28771da177e4SLinus Torvalds 			return err;
2878*2ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
28791da177e4SLinus Torvalds 	}
28801da177e4SLinus Torvalds 
2881352f7f91STakashi Iwai 	path->active = true;
28820186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
28830186f4f4STakashi Iwai 	if (err < 0)
28840186f4f4STakashi Iwai 		return err;
2885e4a395e7STakashi Iwai 
2886e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
2887e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
2888e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
2889e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
2890e4a395e7STakashi Iwai 		if (path) {
2891e4a395e7STakashi Iwai 			print_nid_path("loopback-merge", path);
2892e4a395e7STakashi Iwai 			path->active = true;
2893e4a395e7STakashi Iwai 			spec->loopback_merge_path =
2894e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
2895e4a395e7STakashi Iwai 		}
2896e4a395e7STakashi Iwai 	}
2897e4a395e7STakashi Iwai 
2898352f7f91STakashi Iwai 	return 0;
28991da177e4SLinus Torvalds }
29001da177e4SLinus Torvalds 
2901352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
29021da177e4SLinus Torvalds {
2903352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2904352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2905352f7f91STakashi Iwai }
2906352f7f91STakashi Iwai 
2907352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2908352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2909352f7f91STakashi Iwai {
2910352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2911352f7f91STakashi Iwai 	hda_nid_t nid;
2912352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2913352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2914352f7f91STakashi Iwai 	int i, nums = 0;
2915352f7f91STakashi Iwai 
2916352f7f91STakashi Iwai 	nid = codec->start_nid;
2917352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2918352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2919352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2920352f7f91STakashi Iwai 
2921352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2922352f7f91STakashi Iwai 			continue;
2923352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2924352f7f91STakashi Iwai 		if (++nums >= max_nums)
2925352f7f91STakashi Iwai 			break;
2926352f7f91STakashi Iwai 	}
2927352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
29280ffd534eSTakashi Iwai 
29290ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
29300ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
29310ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
29320ffd534eSTakashi Iwai 
2933352f7f91STakashi Iwai 	return nums;
2934352f7f91STakashi Iwai }
2935352f7f91STakashi Iwai 
2936352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2937352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2938352f7f91STakashi Iwai  */
2939352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2940352f7f91STakashi Iwai {
2941352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2942352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
29433a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2944352f7f91STakashi Iwai 	int i, n, nums;
2945352f7f91STakashi Iwai 
2946352f7f91STakashi Iwai 	nums = 0;
29473a65bcdcSTakashi Iwai 	ok_bits = 0;
2948352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2949352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
29503a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2951352f7f91STakashi Iwai 				break;
2952352f7f91STakashi Iwai 		}
29533a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
29543a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
29553a65bcdcSTakashi Iwai 			nums++;
29563a65bcdcSTakashi Iwai 		}
2957352f7f91STakashi Iwai 	}
2958352f7f91STakashi Iwai 
29593a65bcdcSTakashi Iwai 	if (!ok_bits) {
2960352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2961352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2962352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
29633a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2964352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2965352f7f91STakashi Iwai 					break;
2966352f7f91STakashi Iwai 				}
2967352f7f91STakashi Iwai 			}
2968352f7f91STakashi Iwai 		}
2969352f7f91STakashi Iwai 
2970352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2971352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2972352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
29733a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
29743a65bcdcSTakashi Iwai 		nums = 0;
29753a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
29763a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
29773a65bcdcSTakashi Iwai 				continue;
29783a65bcdcSTakashi Iwai 			if (n != nums) {
29793a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2980980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2981980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2982980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
29833a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
29843a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
29853a65bcdcSTakashi Iwai 				}
2986980428ceSTakashi Iwai 			}
29873a65bcdcSTakashi Iwai 			nums++;
29883a65bcdcSTakashi Iwai 		}
2989352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2990352f7f91STakashi Iwai 	}
2991352f7f91STakashi Iwai 
2992967303daSTakashi Iwai 	if (imux->num_items == 1 ||
2993967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
2994352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2995352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2996352f7f91STakashi Iwai 	}
2997352f7f91STakashi Iwai 
2998352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2999352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3000352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3001352f7f91STakashi Iwai 
30021da177e4SLinus Torvalds 	return 0;
30031da177e4SLinus Torvalds }
30041da177e4SLinus Torvalds 
3005f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3006f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
30079dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
30089dba205bSTakashi Iwai 				const char *label, int anchor)
3009f3fc0b0bSTakashi Iwai {
3010f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3011f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3012f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3013f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3014f3fc0b0bSTakashi Iwai 	int c;
3015f3fc0b0bSTakashi Iwai 
3016f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3017f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3018f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3019f3fc0b0bSTakashi Iwai 
3020f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3021f3fc0b0bSTakashi Iwai 			continue;
3022f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3023f3fc0b0bSTakashi Iwai 		if (!path)
3024f3fc0b0bSTakashi Iwai 			continue;
3025f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
3026f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3027f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3028f3fc0b0bSTakashi Iwai 
3029f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3030967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3031967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3032f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
30339dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
3034f3fc0b0bSTakashi Iwai 			imux_added = true;
3035f3fc0b0bSTakashi Iwai 		}
3036f3fc0b0bSTakashi Iwai 	}
3037f3fc0b0bSTakashi Iwai 
3038f3fc0b0bSTakashi Iwai 	return 0;
3039f3fc0b0bSTakashi Iwai }
3040f3fc0b0bSTakashi Iwai 
30411da177e4SLinus Torvalds /*
3042352f7f91STakashi Iwai  * create playback/capture controls for input pins
30431da177e4SLinus Torvalds  */
30449dba205bSTakashi Iwai 
3045c970042cSTakashi Iwai /* fill the label for each input at first */
3046c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3047c970042cSTakashi Iwai {
3048c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3049c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3050c970042cSTakashi Iwai 	int i;
3051c970042cSTakashi Iwai 
3052c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3053c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3054c970042cSTakashi Iwai 		const char *label;
3055c970042cSTakashi Iwai 		int j, idx;
3056c970042cSTakashi Iwai 
3057c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3058c970042cSTakashi Iwai 			continue;
3059c970042cSTakashi Iwai 
3060c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3061c970042cSTakashi Iwai 		idx = 0;
30628e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3063c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3064c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3065c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3066c970042cSTakashi Iwai 				break;
3067c970042cSTakashi Iwai 			}
3068c970042cSTakashi Iwai 		}
3069c970042cSTakashi Iwai 
3070c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3071c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3072c970042cSTakashi Iwai 	}
3073c970042cSTakashi Iwai 
3074c970042cSTakashi Iwai 	return 0;
3075c970042cSTakashi Iwai }
3076c970042cSTakashi Iwai 
30779dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
30789dba205bSTakashi Iwai 
3079352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3080a7da6ce5STakashi Iwai {
3081352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3082352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3083352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3084352f7f91STakashi Iwai 	int num_adcs;
3085c970042cSTakashi Iwai 	int i, err;
30862c12c30dSTakashi Iwai 	unsigned int val;
3087a7da6ce5STakashi Iwai 
3088352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3089352f7f91STakashi Iwai 	if (num_adcs < 0)
3090352f7f91STakashi Iwai 		return 0;
3091352f7f91STakashi Iwai 
3092c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3093c970042cSTakashi Iwai 	if (err < 0)
3094c970042cSTakashi Iwai 		return err;
3095c970042cSTakashi Iwai 
3096352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3097352f7f91STakashi Iwai 		hda_nid_t pin;
3098352f7f91STakashi Iwai 
3099352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3100352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3101352f7f91STakashi Iwai 			continue;
3102352f7f91STakashi Iwai 
31032c12c30dSTakashi Iwai 		val = PIN_IN;
31042c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
31052c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
310693c9d8aeSTakashi Iwai 		if (pin != spec->hp_mic_pin)
31072c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
31082c12c30dSTakashi Iwai 
3109352f7f91STakashi Iwai 		if (mixer) {
3110352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3111196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3112c970042cSTakashi Iwai 						       spec->input_labels[i],
3113c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3114c970042cSTakashi Iwai 						       mixer);
3115a7da6ce5STakashi Iwai 				if (err < 0)
3116a7da6ce5STakashi Iwai 					return err;
3117a7da6ce5STakashi Iwai 			}
3118352f7f91STakashi Iwai 		}
3119352f7f91STakashi Iwai 
3120c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3121c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3122f3fc0b0bSTakashi Iwai 		if (err < 0)
3123f3fc0b0bSTakashi Iwai 			return err;
312429476558STakashi Iwai 
3125f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
312629476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
312729476558STakashi Iwai 			if (err < 0)
312829476558STakashi Iwai 				return err;
312929476558STakashi Iwai 		}
3130352f7f91STakashi Iwai 	}
3131f3fc0b0bSTakashi Iwai 
3132f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
31339dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3134f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3135f3fc0b0bSTakashi Iwai 		if (err < 0)
3136f3fc0b0bSTakashi Iwai 			return err;
3137352f7f91STakashi Iwai 	}
3138352f7f91STakashi Iwai 
3139a7da6ce5STakashi Iwai 	return 0;
3140a7da6ce5STakashi Iwai }
3141a7da6ce5STakashi Iwai 
31421da177e4SLinus Torvalds 
3143352f7f91STakashi Iwai /*
3144352f7f91STakashi Iwai  * input source mux
3145352f7f91STakashi Iwai  */
3146352f7f91STakashi Iwai 
3147c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3148c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3149352f7f91STakashi Iwai {
3150352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3151b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3152b56fa1edSDavid Henningsson 		snd_BUG();
3153b56fa1edSDavid Henningsson 		return NULL;
3154b56fa1edSDavid Henningsson 	}
3155352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3156352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3157d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3158b56fa1edSDavid Henningsson 		snd_BUG();
3159b56fa1edSDavid Henningsson 		return NULL;
3160b56fa1edSDavid Henningsson 	}
3161c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
316297ec558aSTakashi Iwai }
3163352f7f91STakashi Iwai 
3164352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3165352f7f91STakashi Iwai 		      unsigned int idx);
3166352f7f91STakashi Iwai 
3167352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3168352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3169352f7f91STakashi Iwai {
3170352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3171352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3172352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3173352f7f91STakashi Iwai }
3174352f7f91STakashi Iwai 
3175352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3176352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3177352f7f91STakashi Iwai {
3178352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3179352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
31802a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
31812a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3182352f7f91STakashi Iwai 
3183352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
31841da177e4SLinus Torvalds 	return 0;
31851da177e4SLinus Torvalds }
31861da177e4SLinus Torvalds 
3187352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3188352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
31891da177e4SLinus Torvalds {
3190352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
31912a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3192352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3193352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3194352f7f91STakashi Iwai }
3195352f7f91STakashi Iwai 
3196352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
31971da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3198352f7f91STakashi Iwai 	.name = "Input Source",
3199352f7f91STakashi Iwai 	.info = mux_enum_info,
3200352f7f91STakashi Iwai 	.get = mux_enum_get,
3201352f7f91STakashi Iwai 	.put = mux_enum_put,
32021da177e4SLinus Torvalds };
3203071c73adSTakashi Iwai 
320447d46abbSTakashi Iwai /*
320547d46abbSTakashi Iwai  * capture volume and capture switch ctls
320647d46abbSTakashi Iwai  */
320747d46abbSTakashi Iwai 
3208352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3209352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3210071c73adSTakashi Iwai 
321147d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3212352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3213352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3214352f7f91STakashi Iwai 			  put_call_t func, int type)
3215352f7f91STakashi Iwai {
3216352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3217352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3218352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3219352f7f91STakashi Iwai 	struct nid_path *path;
3220352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3221071c73adSTakashi Iwai 
3222352f7f91STakashi Iwai 	imux = &spec->input_mux;
3223a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3224352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
322547d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
322647d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
322747d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
322847d46abbSTakashi Iwai 	 */
3229352f7f91STakashi Iwai 	codec->cached_write = 1;
3230352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3231c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3232c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3233352f7f91STakashi Iwai 			continue;
3234352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3235352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3236352f7f91STakashi Iwai 		if (err < 0)
3237352f7f91STakashi Iwai 			goto error;
3238352f7f91STakashi Iwai 	}
3239352f7f91STakashi Iwai  error:
3240352f7f91STakashi Iwai 	codec->cached_write = 0;
3241352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3242dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec); /* flush the updates */
3243352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
3244a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3245352f7f91STakashi Iwai 	return err;
3246352f7f91STakashi Iwai }
3247352f7f91STakashi Iwai 
3248352f7f91STakashi Iwai /* capture volume ctl callbacks */
3249352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3250352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3251352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3252352f7f91STakashi Iwai 
3253352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3254352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3255352f7f91STakashi Iwai {
3256352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3257352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3258352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3259352f7f91STakashi Iwai }
3260352f7f91STakashi Iwai 
3261352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3262352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3263352f7f91STakashi Iwai 	.name = "Capture Volume",
3264352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3265352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3266352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3267352f7f91STakashi Iwai 	.info = cap_vol_info,
3268352f7f91STakashi Iwai 	.get = cap_vol_get,
3269352f7f91STakashi Iwai 	.put = cap_vol_put,
3270352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3271352f7f91STakashi Iwai };
3272352f7f91STakashi Iwai 
3273352f7f91STakashi Iwai /* capture switch ctl callbacks */
3274352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3275352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3276352f7f91STakashi Iwai 
3277352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3278352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3279352f7f91STakashi Iwai {
3280a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3281352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3282352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3283352f7f91STakashi Iwai }
3284352f7f91STakashi Iwai 
3285352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3286352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3287352f7f91STakashi Iwai 	.name = "Capture Switch",
3288352f7f91STakashi Iwai 	.info = cap_sw_info,
3289352f7f91STakashi Iwai 	.get = cap_sw_get,
3290352f7f91STakashi Iwai 	.put = cap_sw_put,
3291352f7f91STakashi Iwai };
3292352f7f91STakashi Iwai 
3293352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3294352f7f91STakashi Iwai {
3295352f7f91STakashi Iwai 	hda_nid_t nid;
3296352f7f91STakashi Iwai 	int i, depth;
3297352f7f91STakashi Iwai 
3298352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3299352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3300352f7f91STakashi Iwai 		if (depth >= path->depth)
3301352f7f91STakashi Iwai 			return -EINVAL;
3302352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3303352f7f91STakashi Iwai 		nid = path->path[i];
3304352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3305352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3306352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3307352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3308352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3309352f7f91STakashi Iwai 				int idx = path->idx[i];
3310352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3311352f7f91STakashi Iwai 					idx = 0;
3312352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3313352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3314352f7f91STakashi Iwai 			}
3315352f7f91STakashi Iwai 		}
3316352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3317352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3318352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3319352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3320352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3321352f7f91STakashi Iwai 				int idx = path->idx[i];
3322352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3323352f7f91STakashi Iwai 					idx = 0;
3324352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3325352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3326352f7f91STakashi Iwai 			}
3327352f7f91STakashi Iwai 		}
3328352f7f91STakashi Iwai 	}
3329352f7f91STakashi Iwai 	return 0;
3330352f7f91STakashi Iwai }
3331352f7f91STakashi Iwai 
3332352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3333352f7f91STakashi Iwai {
3334352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3335352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3336352f7f91STakashi Iwai 	unsigned int val;
3337352f7f91STakashi Iwai 	int i;
3338352f7f91STakashi Iwai 
3339352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3340352f7f91STakashi Iwai 		return false;
3341352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3342352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3343352f7f91STakashi Iwai 			continue;
3344352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3345352f7f91STakashi Iwai 			return false;
3346352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3347352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3348352f7f91STakashi Iwai 	}
3349352f7f91STakashi Iwai 	return false;
3350352f7f91STakashi Iwai }
3351352f7f91STakashi Iwai 
3352a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3353a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3354a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3355a35bd1e3STakashi Iwai {
3356a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3357a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3358a35bd1e3STakashi Iwai 	int ret;
3359a35bd1e3STakashi Iwai 
3360a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3361a35bd1e3STakashi Iwai 	if (ret < 0)
3362a35bd1e3STakashi Iwai 		return ret;
3363a35bd1e3STakashi Iwai 
3364a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
3365a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3366a35bd1e3STakashi Iwai 
3367a35bd1e3STakashi Iwai 	return ret;
3368a35bd1e3STakashi Iwai }
3369a35bd1e3STakashi Iwai 
3370352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3371352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3372352f7f91STakashi Iwai 			      bool inv_dmic)
3373352f7f91STakashi Iwai {
3374352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3375975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3376352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3377352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3378352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3379a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3380352f7f91STakashi Iwai 
3381352f7f91STakashi Iwai 	if (!ctl)
3382352f7f91STakashi Iwai 		return 0;
3383352f7f91STakashi Iwai 
3384352f7f91STakashi Iwai 	if (label)
3385352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3386352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3387352f7f91STakashi Iwai 	else
3388352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3389352f7f91STakashi Iwai 			 "Capture %s", sfx);
3390a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3391352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3392a35bd1e3STakashi Iwai 	if (!knew)
3393a35bd1e3STakashi Iwai 		return -ENOMEM;
3394a90229e0STakashi Iwai 	if (is_switch)
3395a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3396a35bd1e3STakashi Iwai 	if (!inv_dmic)
3397a35bd1e3STakashi Iwai 		return 0;
3398352f7f91STakashi Iwai 
3399352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3400352f7f91STakashi Iwai 	if (label)
3401352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3402352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3403352f7f91STakashi Iwai 	else
3404352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3405352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3406a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3407352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3408a35bd1e3STakashi Iwai 	if (!knew)
3409a35bd1e3STakashi Iwai 		return -ENOMEM;
3410a90229e0STakashi Iwai 	if (is_switch)
3411a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3412a35bd1e3STakashi Iwai 	return 0;
3413352f7f91STakashi Iwai }
3414352f7f91STakashi Iwai 
3415352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3416352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3417352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3418352f7f91STakashi Iwai 				     bool inv_dmic)
3419352f7f91STakashi Iwai {
3420352f7f91STakashi Iwai 	int err;
3421352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3422352f7f91STakashi Iwai 	if (err < 0)
3423352f7f91STakashi Iwai 		return err;
3424352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3425071c73adSTakashi Iwai 	if (err < 0)
3426071c73adSTakashi Iwai 		return err;
3427071c73adSTakashi Iwai 	return 0;
34281da177e4SLinus Torvalds }
3429071c73adSTakashi Iwai 
3430352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3431352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3432352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3433352f7f91STakashi Iwai {
3434352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3435352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3436352f7f91STakashi Iwai 
3437352f7f91STakashi Iwai 	if (vol_ctl) {
343812c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3439352f7f91STakashi Iwai 		if (!knew)
3440352f7f91STakashi Iwai 			return -ENOMEM;
3441352f7f91STakashi Iwai 		knew->index = idx;
3442352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3443352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3444352f7f91STakashi Iwai 	}
3445352f7f91STakashi Iwai 	if (sw_ctl) {
344612c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3447352f7f91STakashi Iwai 		if (!knew)
3448352f7f91STakashi Iwai 			return -ENOMEM;
3449352f7f91STakashi Iwai 		knew->index = idx;
3450352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3451352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3452352f7f91STakashi Iwai 	}
3453352f7f91STakashi Iwai 	return 0;
3454352f7f91STakashi Iwai }
3455352f7f91STakashi Iwai 
3456352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3457352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3458352f7f91STakashi Iwai {
3459352f7f91STakashi Iwai 	struct nid_path *path;
3460352f7f91STakashi Iwai 	unsigned int ctl;
3461352f7f91STakashi Iwai 	int i;
3462352f7f91STakashi Iwai 
3463c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3464352f7f91STakashi Iwai 	if (!path)
3465352f7f91STakashi Iwai 		return 0;
3466352f7f91STakashi Iwai 	ctl = path->ctls[type];
3467352f7f91STakashi Iwai 	if (!ctl)
3468352f7f91STakashi Iwai 		return 0;
3469352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3470c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3471352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3472352f7f91STakashi Iwai 			return 0;
3473352f7f91STakashi Iwai 	}
3474352f7f91STakashi Iwai 	return ctl;
3475352f7f91STakashi Iwai }
3476352f7f91STakashi Iwai 
3477352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3478352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3479352f7f91STakashi Iwai {
3480352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3481352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3482c970042cSTakashi Iwai 	int i, err, type;
3483352f7f91STakashi Iwai 
3484352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3485352f7f91STakashi Iwai 		bool inv_dmic;
3486c970042cSTakashi Iwai 		int idx;
34879dba205bSTakashi Iwai 
3488c970042cSTakashi Iwai 		idx = imux->items[i].index;
3489c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
34909dba205bSTakashi Iwai 			continue;
3491352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3492352f7f91STakashi Iwai 
3493352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3494c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3495c970042cSTakashi Iwai 						 spec->input_labels[idx],
3496c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3497c970042cSTakashi Iwai 						 type,
3498352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3499352f7f91STakashi Iwai 						 inv_dmic);
3500d13bd412STakashi Iwai 			if (err < 0)
3501071c73adSTakashi Iwai 				return err;
3502352f7f91STakashi Iwai 		}
3503352f7f91STakashi Iwai 	}
3504071c73adSTakashi Iwai 	return 0;
3505352f7f91STakashi Iwai }
3506071c73adSTakashi Iwai 
3507352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3508352f7f91STakashi Iwai {
3509352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3510352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3511352f7f91STakashi Iwai 	int i, n, nums, err;
3512352f7f91STakashi Iwai 
3513352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3514352f7f91STakashi Iwai 		nums = 1;
3515352f7f91STakashi Iwai 	else
3516352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3517352f7f91STakashi Iwai 
3518352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3519352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3520624d914dSTakashi Iwai 		const char *name;
3521624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3522624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3523352f7f91STakashi Iwai 		if (!knew)
3524352f7f91STakashi Iwai 			return -ENOMEM;
3525352f7f91STakashi Iwai 		knew->count = nums;
3526352f7f91STakashi Iwai 	}
3527352f7f91STakashi Iwai 
3528352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3529352f7f91STakashi Iwai 		bool multi = false;
353099a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3531352f7f91STakashi Iwai 		bool inv_dmic = false;
3532352f7f91STakashi Iwai 		int vol, sw;
3533352f7f91STakashi Iwai 
3534352f7f91STakashi Iwai 		vol = sw = 0;
3535352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3536352f7f91STakashi Iwai 			struct nid_path *path;
3537c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3538352f7f91STakashi Iwai 			if (!path)
3539352f7f91STakashi Iwai 				continue;
3540352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3541352f7f91STakashi Iwai 			if (!vol)
3542352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
354399a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3544352f7f91STakashi Iwai 				multi = true;
354599a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
354699a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
354799a5592dSDavid Henningsson 					multi_cap_vol = true;
354899a5592dSDavid Henningsson 			}
3549352f7f91STakashi Iwai 			if (!sw)
3550352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
355199a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3552352f7f91STakashi Iwai 				multi = true;
355399a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
355499a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
355599a5592dSDavid Henningsson 					multi_cap_vol = true;
355699a5592dSDavid Henningsson 			}
3557352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3558352f7f91STakashi Iwai 				inv_dmic = true;
3559352f7f91STakashi Iwai 		}
3560352f7f91STakashi Iwai 
3561352f7f91STakashi Iwai 		if (!multi)
3562352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3563352f7f91STakashi Iwai 							inv_dmic);
3564ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3565352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3566352f7f91STakashi Iwai 		else
3567352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3568d13bd412STakashi Iwai 		if (err < 0)
3569071c73adSTakashi Iwai 			return err;
3570071c73adSTakashi Iwai 	}
3571071c73adSTakashi Iwai 
35721da177e4SLinus Torvalds 	return 0;
35731da177e4SLinus Torvalds }
35741da177e4SLinus Torvalds 
3575352f7f91STakashi Iwai /*
3576352f7f91STakashi Iwai  * add mic boosts if needed
3577352f7f91STakashi Iwai  */
35786f7c83afSTakashi Iwai 
35796f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
35806f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
35816f7c83afSTakashi Iwai 			    int dir, int idx)
35826f7c83afSTakashi Iwai {
35836f7c83afSTakashi Iwai 	unsigned int step;
35846f7c83afSTakashi Iwai 
35856f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
35866f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
35876f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
35886f7c83afSTakashi Iwai 		return false;
35896f7c83afSTakashi Iwai 
35906f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
35916f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
35926f7c83afSTakashi Iwai 	if (step < 0x20)
35936f7c83afSTakashi Iwai 		return false;
35946f7c83afSTakashi Iwai 	return true;
35956f7c83afSTakashi Iwai }
35966f7c83afSTakashi Iwai 
35976f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
35986f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
35996f7c83afSTakashi Iwai 				       struct nid_path *path)
36006f7c83afSTakashi Iwai {
36016f7c83afSTakashi Iwai 	unsigned int val = 0;
36026f7c83afSTakashi Iwai 	hda_nid_t nid;
36036f7c83afSTakashi Iwai 	int depth;
36046f7c83afSTakashi Iwai 
36056f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
36066f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
36076f7c83afSTakashi Iwai 			break;
36086f7c83afSTakashi Iwai 		nid = path->path[depth];
36096f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
36106f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
36116f7c83afSTakashi Iwai 			break;
36126f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
36136f7c83afSTakashi Iwai 					   path->idx[depth])) {
36146f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
36156f7c83afSTakashi Iwai 						  HDA_INPUT);
36166f7c83afSTakashi Iwai 			break;
36176f7c83afSTakashi Iwai 		}
36186f7c83afSTakashi Iwai 	}
36196f7c83afSTakashi Iwai 
36206f7c83afSTakashi Iwai 	return val;
36216f7c83afSTakashi Iwai }
36226f7c83afSTakashi Iwai 
3623352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3624352f7f91STakashi Iwai {
3625352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3626352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
36276f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3628a35bd1e3STakashi Iwai 	int i;
3629352f7f91STakashi Iwai 
36306f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
36316f7c83afSTakashi Iwai 		return 0;
36326f7c83afSTakashi Iwai 
36336f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3634352f7f91STakashi Iwai 		struct nid_path *path;
3635352f7f91STakashi Iwai 		unsigned int val;
36366f7c83afSTakashi Iwai 		int idx;
3637975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3638352f7f91STakashi Iwai 
36396f7c83afSTakashi Iwai 		idx = imux->items[i].index;
36406f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
364102aba550SDavid Henningsson 			continue;
364202aba550SDavid Henningsson 
36436f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
36441799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
36456f7c83afSTakashi Iwai 			continue;
36466f7c83afSTakashi Iwai 
36476f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
36486f7c83afSTakashi Iwai 		if (!path)
36496f7c83afSTakashi Iwai 			continue;
36506f7c83afSTakashi Iwai 
36516f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
36526f7c83afSTakashi Iwai 		if (!val)
36536f7c83afSTakashi Iwai 			continue;
36546f7c83afSTakashi Iwai 
36556f7c83afSTakashi Iwai 		/* create a boost control */
3656352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
36576f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3658a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3659a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3660a35bd1e3STakashi Iwai 			return -ENOMEM;
3661352f7f91STakashi Iwai 
3662352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3663352f7f91STakashi Iwai 	}
3664352f7f91STakashi Iwai 	return 0;
3665352f7f91STakashi Iwai }
3666352f7f91STakashi Iwai 
3667352f7f91STakashi Iwai /*
3668352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3669352f7f91STakashi Iwai  */
3670352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3671352f7f91STakashi Iwai {
3672352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
36730c8c0f56STakashi Iwai 	struct nid_path *path;
3674352f7f91STakashi Iwai 	int i, nums;
36752c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3676352f7f91STakashi Iwai 
3677352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3678352f7f91STakashi Iwai 	nums = 0;
3679352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
36802c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3681352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3682352f7f91STakashi Iwai 		if (!dig_nid)
3683352f7f91STakashi Iwai 			continue;
36843ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
36850c8c0f56STakashi Iwai 		if (!path)
3686352f7f91STakashi Iwai 			continue;
36870c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3688e1284af7STakashi Iwai 		path->active = true;
3689196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
36902c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3691352f7f91STakashi Iwai 		if (!nums) {
3692352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3693352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3694352f7f91STakashi Iwai 		} else {
3695352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3696352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3697352f7f91STakashi Iwai 			break;
3698352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3699352f7f91STakashi Iwai 		}
3700352f7f91STakashi Iwai 		nums++;
3701352f7f91STakashi Iwai 	}
3702352f7f91STakashi Iwai 
3703352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
37042c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3705352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3706352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3707352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3708352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3709352f7f91STakashi Iwai 				continue;
3710352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3711352f7f91STakashi Iwai 				continue;
37122c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3713352f7f91STakashi Iwai 			if (path) {
37140c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3715352f7f91STakashi Iwai 				path->active = true;
3716352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
37172430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
37182c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3719352f7f91STakashi Iwai 				break;
3720352f7f91STakashi Iwai 			}
3721352f7f91STakashi Iwai 		}
3722352f7f91STakashi Iwai 	}
3723352f7f91STakashi Iwai }
3724352f7f91STakashi Iwai 
37251da177e4SLinus Torvalds 
37261da177e4SLinus Torvalds /*
3727352f7f91STakashi Iwai  * input MUX handling
37281da177e4SLinus Torvalds  */
37291da177e4SLinus Torvalds 
3730352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3731352f7f91STakashi Iwai 
3732352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3733352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3734352f7f91STakashi Iwai 		      unsigned int idx)
3735352f7f91STakashi Iwai {
3736352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3737352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
373855196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3739352f7f91STakashi Iwai 
3740352f7f91STakashi Iwai 	imux = &spec->input_mux;
3741352f7f91STakashi Iwai 	if (!imux->num_items)
37421da177e4SLinus Torvalds 		return 0;
37431da177e4SLinus Torvalds 
3744352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3745352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3746352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3747352f7f91STakashi Iwai 		return 0;
3748352f7f91STakashi Iwai 
374955196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
375055196fffSTakashi Iwai 	if (!old_path)
3751352f7f91STakashi Iwai 		return 0;
375255196fffSTakashi Iwai 	if (old_path->active)
375355196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3754352f7f91STakashi Iwai 
3755352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3756352f7f91STakashi Iwai 
3757967303daSTakashi Iwai 	if (spec->hp_mic)
3758967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3759352f7f91STakashi Iwai 
3760352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3761352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3762352f7f91STakashi Iwai 
3763c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3764352f7f91STakashi Iwai 	if (!path)
3765352f7f91STakashi Iwai 		return 0;
3766352f7f91STakashi Iwai 	if (path->active)
3767352f7f91STakashi Iwai 		return 0;
3768352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3769352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3770a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
377155196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
37721da177e4SLinus Torvalds 	return 1;
37731da177e4SLinus Torvalds }
37741da177e4SLinus Torvalds 
37751da177e4SLinus Torvalds 
37761da177e4SLinus Torvalds /*
3777352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
37781da177e4SLinus Torvalds  */
3779352f7f91STakashi Iwai 
3780352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3781352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
37821da177e4SLinus Torvalds {
378360ea8ca2STakashi Iwai 	int i;
378460ea8ca2STakashi Iwai 	bool present = false;
37851da177e4SLinus Torvalds 
3786352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3787352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3788352f7f91STakashi Iwai 		if (!nid)
3789352f7f91STakashi Iwai 			break;
37900b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
37910b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
37920b4df931STakashi Iwai 			continue;
379360ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
379460ea8ca2STakashi Iwai 			present = true;
37951da177e4SLinus Torvalds 	}
3796352f7f91STakashi Iwai 	return present;
37971da177e4SLinus Torvalds }
37981da177e4SLinus Torvalds 
3799352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3800352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3801e80c60f3STakashi Iwai 			int *paths, bool mute)
38021da177e4SLinus Torvalds {
3803352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3804352f7f91STakashi Iwai 	int i;
38051da177e4SLinus Torvalds 
3806352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3807352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3808967303daSTakashi Iwai 		unsigned int val, oldval;
3809352f7f91STakashi Iwai 		if (!nid)
3810352f7f91STakashi Iwai 			break;
38117eebffd3STakashi Iwai 
38127eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
3813e80c60f3STakashi Iwai 			struct nid_path *path;
3814e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
3815e80c60f3STakashi Iwai 
3816e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
3817e80c60f3STakashi Iwai 			if (!path)
3818e80c60f3STakashi Iwai 				continue;
3819e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
3820e80c60f3STakashi Iwai 			if (!mute_nid)
3821e80c60f3STakashi Iwai 				continue;
38227eebffd3STakashi Iwai 			if (mute)
3823e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
38247eebffd3STakashi Iwai 			else
3825e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
38267eebffd3STakashi Iwai 			set_pin_eapd(codec, nid, !mute);
38277eebffd3STakashi Iwai 			continue;
38287eebffd3STakashi Iwai 		}
38297eebffd3STakashi Iwai 
3830967303daSTakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
3831967303daSTakashi Iwai 		if (oldval & PIN_IN)
3832967303daSTakashi Iwai 			continue; /* no mute for inputs */
3833352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3834352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3835352f7f91STakashi Iwai 		 */
38362c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
3837967303daSTakashi Iwai 			val = oldval & ~PIN_HP;
38382c12c30dSTakashi Iwai 		else
3839352f7f91STakashi Iwai 			val = 0;
38402c12c30dSTakashi Iwai 		if (!mute)
3841967303daSTakashi Iwai 			val |= oldval;
38422c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
38432c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
38442c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
38452c12c30dSTakashi Iwai 		 * init / resume again
38462c12c30dSTakashi Iwai 		 */
38472c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3848d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3849352f7f91STakashi Iwai 	}
3850352f7f91STakashi Iwai }
38511da177e4SLinus Torvalds 
3852352f7f91STakashi Iwai /* Toggle outputs muting */
38535d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3854352f7f91STakashi Iwai {
3855352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3856e80c60f3STakashi Iwai 	int *paths;
3857352f7f91STakashi Iwai 	int on;
3858352f7f91STakashi Iwai 
3859352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3860352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3861352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3862352f7f91STakashi Iwai 	 */
3863e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3864e80c60f3STakashi Iwai 		paths = spec->out_paths;
3865e80c60f3STakashi Iwai 	else
3866e80c60f3STakashi Iwai 		paths = spec->hp_paths;
3867352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3868e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
3869352f7f91STakashi Iwai 
3870352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3871352f7f91STakashi Iwai 		on = 0;
3872352f7f91STakashi Iwai 	else
3873352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3874352f7f91STakashi Iwai 	on |= spec->master_mute;
387547b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3876e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3877e80c60f3STakashi Iwai 		paths = spec->out_paths;
3878e80c60f3STakashi Iwai 	else
3879e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
3880352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
3881e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
3882352f7f91STakashi Iwai 
3883352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3884352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3885352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3886352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3887352f7f91STakashi Iwai 		return;
3888352f7f91STakashi Iwai 	if (!spec->automute_lo)
3889352f7f91STakashi Iwai 		on = 0;
3890352f7f91STakashi Iwai 	else
3891352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3892352f7f91STakashi Iwai 	on |= spec->master_mute;
389347b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3894e80c60f3STakashi Iwai 	paths = spec->out_paths;
3895352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3896e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
3897352f7f91STakashi Iwai }
38985d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3899352f7f91STakashi Iwai 
3900352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3901352f7f91STakashi Iwai {
3902352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3903352f7f91STakashi Iwai 	if (spec->automute_hook)
3904352f7f91STakashi Iwai 		spec->automute_hook(codec);
3905352f7f91STakashi Iwai 	else
39065d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
39077eebffd3STakashi Iwai 
39087eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
39097eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
39107eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
3911352f7f91STakashi Iwai }
3912352f7f91STakashi Iwai 
3913352f7f91STakashi Iwai /* standard HP-automute helper */
39145d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3915352f7f91STakashi Iwai {
3916352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
391792603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
391892603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
3919352f7f91STakashi Iwai 
392092603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
392192603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
392292603c59STakashi Iwai 		pins++;
392392603c59STakashi Iwai 		num_pins--;
392492603c59STakashi Iwai 	}
392592603c59STakashi Iwai 
392692603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
3927352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3928352f7f91STakashi Iwai 		return;
3929352f7f91STakashi Iwai 	call_update_outputs(codec);
3930352f7f91STakashi Iwai }
39315d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3932352f7f91STakashi Iwai 
3933352f7f91STakashi Iwai /* standard line-out-automute helper */
39345d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3935352f7f91STakashi Iwai {
3936352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3937352f7f91STakashi Iwai 
3938352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3939352f7f91STakashi Iwai 		return;
3940352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3941352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3942352f7f91STakashi Iwai 		return;
3943352f7f91STakashi Iwai 
3944352f7f91STakashi Iwai 	spec->line_jack_present =
3945352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3946352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3947352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3948352f7f91STakashi Iwai 		return;
3949352f7f91STakashi Iwai 	call_update_outputs(codec);
3950352f7f91STakashi Iwai }
39515d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3952352f7f91STakashi Iwai 
3953352f7f91STakashi Iwai /* standard mic auto-switch helper */
39545d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3955352f7f91STakashi Iwai {
3956352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3957352f7f91STakashi Iwai 	int i;
3958352f7f91STakashi Iwai 
3959352f7f91STakashi Iwai 	if (!spec->auto_mic)
3960352f7f91STakashi Iwai 		return;
3961352f7f91STakashi Iwai 
3962352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
39630b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
39640b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
39650b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
39660b4df931STakashi Iwai 			continue;
396760ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
3968352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3969352f7f91STakashi Iwai 			return;
3970352f7f91STakashi Iwai 		}
3971352f7f91STakashi Iwai 	}
3972352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
39731da177e4SLinus Torvalds }
39745d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
39751da177e4SLinus Torvalds 
397677afe0e9STakashi Iwai /* call appropriate hooks */
397777afe0e9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
397877afe0e9STakashi Iwai {
397977afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
398077afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
398177afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
398277afe0e9STakashi Iwai 	else
398377afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
398477afe0e9STakashi Iwai }
398577afe0e9STakashi Iwai 
398677afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
398777afe0e9STakashi Iwai 			       struct hda_jack_tbl *jack)
398877afe0e9STakashi Iwai {
398977afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
399077afe0e9STakashi Iwai 	if (spec->line_automute_hook)
399177afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
399277afe0e9STakashi Iwai 	else
399377afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
399477afe0e9STakashi Iwai }
399577afe0e9STakashi Iwai 
399677afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
399777afe0e9STakashi Iwai 				struct hda_jack_tbl *jack)
399877afe0e9STakashi Iwai {
399977afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
400077afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
400177afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
400277afe0e9STakashi Iwai 	else
400377afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
400477afe0e9STakashi Iwai }
400577afe0e9STakashi Iwai 
4006963afde9STakashi Iwai /* update jack retasking */
4007963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4008963afde9STakashi Iwai {
4009963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4010963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4011963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4012963afde9STakashi Iwai }
4013963afde9STakashi Iwai 
40141da177e4SLinus Torvalds /*
4015352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
40161da177e4SLinus Torvalds  */
4017352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4018352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4019352f7f91STakashi Iwai {
4020352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4021352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4022352f7f91STakashi Iwai 	static const char * const texts3[] = {
4023352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
40241da177e4SLinus Torvalds 	};
40251da177e4SLinus Torvalds 
4026352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4027352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4028352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4029352f7f91STakashi Iwai }
4030352f7f91STakashi Iwai 
4031352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4032352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4033352f7f91STakashi Iwai {
4034352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4035352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4036352f7f91STakashi Iwai 	unsigned int val = 0;
4037352f7f91STakashi Iwai 	if (spec->automute_speaker)
4038352f7f91STakashi Iwai 		val++;
4039352f7f91STakashi Iwai 	if (spec->automute_lo)
4040352f7f91STakashi Iwai 		val++;
4041352f7f91STakashi Iwai 
4042352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4043352f7f91STakashi Iwai 	return 0;
4044352f7f91STakashi Iwai }
4045352f7f91STakashi Iwai 
4046352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4047352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4048352f7f91STakashi Iwai {
4049352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4050352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4051352f7f91STakashi Iwai 
4052352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4053352f7f91STakashi Iwai 	case 0:
4054352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4055352f7f91STakashi Iwai 			return 0;
4056352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4057352f7f91STakashi Iwai 		spec->automute_lo = 0;
4058352f7f91STakashi Iwai 		break;
4059352f7f91STakashi Iwai 	case 1:
4060352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4061352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4062352f7f91STakashi Iwai 				return 0;
4063352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4064352f7f91STakashi Iwai 			spec->automute_lo = 0;
4065352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4066352f7f91STakashi Iwai 			if (spec->automute_lo)
4067352f7f91STakashi Iwai 				return 0;
4068352f7f91STakashi Iwai 			spec->automute_lo = 1;
4069352f7f91STakashi Iwai 		} else
4070352f7f91STakashi Iwai 			return -EINVAL;
4071352f7f91STakashi Iwai 		break;
4072352f7f91STakashi Iwai 	case 2:
4073352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4074352f7f91STakashi Iwai 			return -EINVAL;
4075352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4076352f7f91STakashi Iwai 			return 0;
4077352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4078352f7f91STakashi Iwai 		spec->automute_lo = 1;
4079352f7f91STakashi Iwai 		break;
4080352f7f91STakashi Iwai 	default:
4081352f7f91STakashi Iwai 		return -EINVAL;
4082352f7f91STakashi Iwai 	}
4083352f7f91STakashi Iwai 	call_update_outputs(codec);
4084352f7f91STakashi Iwai 	return 1;
4085352f7f91STakashi Iwai }
4086352f7f91STakashi Iwai 
4087352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4088352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4089352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4090352f7f91STakashi Iwai 	.info = automute_mode_info,
4091352f7f91STakashi Iwai 	.get = automute_mode_get,
4092352f7f91STakashi Iwai 	.put = automute_mode_put,
4093352f7f91STakashi Iwai };
4094352f7f91STakashi Iwai 
4095352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4096352f7f91STakashi Iwai {
4097352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4098352f7f91STakashi Iwai 
409912c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4100352f7f91STakashi Iwai 		return -ENOMEM;
4101352f7f91STakashi Iwai 	return 0;
4102352f7f91STakashi Iwai }
4103352f7f91STakashi Iwai 
4104352f7f91STakashi Iwai /*
4105352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4106352f7f91STakashi Iwai  * Set up appropriately if really supported
4107352f7f91STakashi Iwai  */
4108352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4109352f7f91STakashi Iwai {
4110352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4111352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4112352f7f91STakashi Iwai 	int present = 0;
4113352f7f91STakashi Iwai 	int i, err;
4114352f7f91STakashi Iwai 
4115f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4116f72706beSTakashi Iwai 		return 0;
4117f72706beSTakashi Iwai 
4118352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4119352f7f91STakashi Iwai 		present++;
4120352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4121352f7f91STakashi Iwai 		present++;
4122352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4123352f7f91STakashi Iwai 		present++;
4124352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4125352f7f91STakashi Iwai 		return 0;
4126352f7f91STakashi Iwai 
4127352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4128352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4129352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4130352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4131352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4132352f7f91STakashi Iwai 	}
4133352f7f91STakashi Iwai 
4134352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4135352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4136352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4137352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4138352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4139352f7f91STakashi Iwai 	}
4140352f7f91STakashi Iwai 
4141352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4142352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4143352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4144352f7f91STakashi Iwai 			continue;
4145352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
4146352f7f91STakashi Iwai 			    nid);
4147352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
414877afe0e9STakashi Iwai 						    call_hp_automute);
4149352f7f91STakashi Iwai 		spec->detect_hp = 1;
4150352f7f91STakashi Iwai 	}
4151352f7f91STakashi Iwai 
4152352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4153352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4154352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4155352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4156352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4157352f7f91STakashi Iwai 					continue;
4158352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
4159352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
4160352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
416177afe0e9STakashi Iwai 								    call_line_automute);
4162352f7f91STakashi Iwai 				spec->detect_lo = 1;
4163352f7f91STakashi Iwai 			}
4164352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4165352f7f91STakashi Iwai 	}
4166352f7f91STakashi Iwai 
4167352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4168352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4169352f7f91STakashi Iwai 
4170352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4171352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4172352f7f91STakashi Iwai 
4173352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4174352f7f91STakashi Iwai 		/* create a control for automute mode */
4175352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4176352f7f91STakashi Iwai 		if (err < 0)
4177352f7f91STakashi Iwai 			return err;
4178352f7f91STakashi Iwai 	}
4179352f7f91STakashi Iwai 	return 0;
4180352f7f91STakashi Iwai }
4181352f7f91STakashi Iwai 
4182352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4183352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4184352f7f91STakashi Iwai {
4185352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4186352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4187352f7f91STakashi Iwai 	int i;
4188352f7f91STakashi Iwai 
4189352f7f91STakashi Iwai 	imux = &spec->input_mux;
4190352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4191352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4192352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4193352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4194352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4195352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4196352f7f91STakashi Iwai 	}
4197352f7f91STakashi Iwai 
4198352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4199352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4200352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4201352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
4202352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
420377afe0e9STakashi Iwai 						    call_mic_autoswitch);
4204352f7f91STakashi Iwai 	return true;
4205352f7f91STakashi Iwai }
4206352f7f91STakashi Iwai 
4207352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4208352f7f91STakashi Iwai {
4209352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4210352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4211352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4212352f7f91STakashi Iwai }
4213352f7f91STakashi Iwai 
4214352f7f91STakashi Iwai /*
4215352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4216352f7f91STakashi Iwai  * Set up if really supported
4217352f7f91STakashi Iwai  */
4218352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4219352f7f91STakashi Iwai {
4220352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4221352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4222352f7f91STakashi Iwai 	unsigned int types;
4223352f7f91STakashi Iwai 	int i, num_pins;
4224352f7f91STakashi Iwai 
4225d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4226d12daf6fSTakashi Iwai 		return 0;
4227d12daf6fSTakashi Iwai 
4228352f7f91STakashi Iwai 	types = 0;
4229352f7f91STakashi Iwai 	num_pins = 0;
4230352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4231352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4232352f7f91STakashi Iwai 		unsigned int attr;
4233352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4234352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4235352f7f91STakashi Iwai 		if (types & (1 << attr))
4236352f7f91STakashi Iwai 			return 0; /* already occupied */
4237352f7f91STakashi Iwai 		switch (attr) {
4238352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4239352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4240352f7f91STakashi Iwai 				return 0; /* invalid type */
4241352f7f91STakashi Iwai 			break;
4242352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4243352f7f91STakashi Iwai 			return 0; /* invalid entry */
4244352f7f91STakashi Iwai 		default:
4245352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4246352f7f91STakashi Iwai 				return 0; /* invalid type */
4247352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4248352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4249352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4250352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4251352f7f91STakashi Iwai 				return 0; /* no unsol support */
4252352f7f91STakashi Iwai 			break;
4253352f7f91STakashi Iwai 		}
4254352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4255352f7f91STakashi Iwai 			return 0;
4256352f7f91STakashi Iwai 		types |= (1 << attr);
4257352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4258352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4259352f7f91STakashi Iwai 		num_pins++;
4260352f7f91STakashi Iwai 	}
4261352f7f91STakashi Iwai 
4262352f7f91STakashi Iwai 	if (num_pins < 2)
4263352f7f91STakashi Iwai 		return 0;
4264352f7f91STakashi Iwai 
4265352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4266352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4267352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4268352f7f91STakashi Iwai 	 */
4269352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4270352f7f91STakashi Iwai 	     compare_attr, NULL);
4271352f7f91STakashi Iwai 
4272352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4273352f7f91STakashi Iwai 		return 0;
4274352f7f91STakashi Iwai 
4275352f7f91STakashi Iwai 	spec->auto_mic = 1;
4276352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4277352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
4278352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4279352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4280352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4281352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4282352f7f91STakashi Iwai 
4283352f7f91STakashi Iwai 	return 0;
4284352f7f91STakashi Iwai }
4285352f7f91STakashi Iwai 
428655196fffSTakashi Iwai /* power_filter hook; make inactive widgets into power down */
428755196fffSTakashi Iwai static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
428855196fffSTakashi Iwai 						  hda_nid_t nid,
428955196fffSTakashi Iwai 						  unsigned int power_state)
429055196fffSTakashi Iwai {
429155196fffSTakashi Iwai 	if (power_state != AC_PWRST_D0)
429255196fffSTakashi Iwai 		return power_state;
429355196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
429455196fffSTakashi Iwai 		return power_state;
4295b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
429655196fffSTakashi Iwai 		return power_state;
429755196fffSTakashi Iwai 	return AC_PWRST_D3;
429855196fffSTakashi Iwai }
429955196fffSTakashi Iwai 
4300352f7f91STakashi Iwai 
43019eb413e5STakashi Iwai /*
43029eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
43039eb413e5STakashi Iwai  *
43049eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4305352f7f91STakashi Iwai  * or a negative error code
4306352f7f91STakashi Iwai  */
4307352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
43089eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4309352f7f91STakashi Iwai {
4310352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4311352f7f91STakashi Iwai 	int err;
4312352f7f91STakashi Iwai 
43131c70a583STakashi Iwai 	parse_user_hints(codec);
43141c70a583STakashi Iwai 
4315e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4316e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4317e4a395e7STakashi Iwai 
43189eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
43199eb413e5STakashi Iwai 		spec->autocfg = *cfg;
43209eb413e5STakashi Iwai 		cfg = &spec->autocfg;
43219eb413e5STakashi Iwai 	}
43229eb413e5STakashi Iwai 
432398bd1115STakashi Iwai 	if (!spec->main_out_badness)
432498bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
432598bd1115STakashi Iwai 	if (!spec->extra_out_badness)
432698bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
432798bd1115STakashi Iwai 
43286fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
43296fc4cb97SDavid Henningsson 
4330352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4331352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4332352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4333352f7f91STakashi Iwai 			spec->no_analog = 1;
4334352f7f91STakashi Iwai 			goto dig_only;
4335352f7f91STakashi Iwai 		}
4336352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
4337352f7f91STakashi Iwai 	}
4338352f7f91STakashi Iwai 
4339352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4340352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4341352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4342352f7f91STakashi Iwai 		/* use HP as primary out */
4343352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4344352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4345352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4346352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4347352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4348352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4349352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4350352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4351352f7f91STakashi Iwai 	}
4352352f7f91STakashi Iwai 
4353352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4354352f7f91STakashi Iwai 	if (err < 0)
4355352f7f91STakashi Iwai 		return err;
4356352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4357352f7f91STakashi Iwai 	if (err < 0)
4358352f7f91STakashi Iwai 		return err;
4359352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4360352f7f91STakashi Iwai 	if (err < 0)
4361352f7f91STakashi Iwai 		return err;
4362352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4363352f7f91STakashi Iwai 	if (err < 0)
4364352f7f91STakashi Iwai 		return err;
4365352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4366352f7f91STakashi Iwai 	if (err < 0)
4367352f7f91STakashi Iwai 		return err;
436838cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
436938cf6f1aSTakashi Iwai 	if (err < 0)
437038cf6f1aSTakashi Iwai 		return err;
4371c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4372c30aa7b2STakashi Iwai 	if (err < 0)
4373c30aa7b2STakashi Iwai 		return err;
4374967303daSTakashi Iwai 	err = create_hp_mic(codec);
4375352f7f91STakashi Iwai 	if (err < 0)
4376352f7f91STakashi Iwai 		return err;
4377352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4378352f7f91STakashi Iwai 	if (err < 0)
4379352f7f91STakashi Iwai 		return err;
4380352f7f91STakashi Iwai 
4381a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4382a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4383a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4384a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4385a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4386a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4387a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4388a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4389352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4390352f7f91STakashi Iwai 					  spec->const_channel_count);
4391352f7f91STakashi Iwai 
4392352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4393352f7f91STakashi Iwai 	if (err < 0)
4394352f7f91STakashi Iwai 		return err;
4395352f7f91STakashi Iwai 
4396352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4397352f7f91STakashi Iwai 	if (err < 0)
4398352f7f91STakashi Iwai 		return err;
4399352f7f91STakashi Iwai 
4400352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4401352f7f91STakashi Iwai 	if (err < 0)
4402352f7f91STakashi Iwai 		return err;
4403352f7f91STakashi Iwai 
4404352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4405352f7f91STakashi Iwai 	if (err < 0)
4406352f7f91STakashi Iwai 		return err;
4407352f7f91STakashi Iwai 
4408352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4409352f7f91STakashi Iwai 	if (err < 0)
4410352f7f91STakashi Iwai 		return err;
4411352f7f91STakashi Iwai 
4412ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4413ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4414ced4cefcSTakashi Iwai 	 */
4415ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4416ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4417ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4418ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4419ced4cefcSTakashi Iwai 		if (err < 0)
4420ced4cefcSTakashi Iwai 			return err;
4421ced4cefcSTakashi Iwai 	}
4422ced4cefcSTakashi Iwai 
4423f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4424978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4425978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4426978e77e7STakashi Iwai 						    cfg->line_out_pins);
4427978e77e7STakashi Iwai 			if (err < 0)
4428978e77e7STakashi Iwai 				return err;
4429978e77e7STakashi Iwai 		}
4430978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4431978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4432978e77e7STakashi Iwai 						    cfg->hp_pins);
4433978e77e7STakashi Iwai 			if (err < 0)
4434978e77e7STakashi Iwai 				return err;
4435978e77e7STakashi Iwai 		}
4436978e77e7STakashi Iwai 	}
4437978e77e7STakashi Iwai 
4438352f7f91STakashi Iwai  dig_only:
4439352f7f91STakashi Iwai 	parse_digital(codec);
4440352f7f91STakashi Iwai 
444155196fffSTakashi Iwai 	if (spec->power_down_unused)
444255196fffSTakashi Iwai 		codec->power_filter = snd_hda_gen_path_power_filter;
444355196fffSTakashi Iwai 
44447504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
44457504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
44467504b6cdSTakashi Iwai 		if (err < 0)
44477504b6cdSTakashi Iwai 			return err;
44487504b6cdSTakashi Iwai 	}
44497504b6cdSTakashi Iwai 
4450352f7f91STakashi Iwai 	return 1;
4451352f7f91STakashi Iwai }
4452352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
4453352f7f91STakashi Iwai 
4454352f7f91STakashi Iwai 
4455352f7f91STakashi Iwai /*
4456352f7f91STakashi Iwai  * Build control elements
4457352f7f91STakashi Iwai  */
4458352f7f91STakashi Iwai 
4459352f7f91STakashi Iwai /* slave controls for virtual master */
4460352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4461352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4462352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4463352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4464ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4465ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
4466ee79c69aSTakashi Iwai 	"Headphone Side",
4467352f7f91STakashi Iwai 	NULL,
4468352f7f91STakashi Iwai };
4469352f7f91STakashi Iwai 
4470352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
4471352f7f91STakashi Iwai {
4472352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4473352f7f91STakashi Iwai 	int err;
4474352f7f91STakashi Iwai 
447536502d02STakashi Iwai 	if (spec->kctls.used) {
4476352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
4477352f7f91STakashi Iwai 		if (err < 0)
4478352f7f91STakashi Iwai 			return err;
447936502d02STakashi Iwai 	}
4480352f7f91STakashi Iwai 
4481352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
4482352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
4483352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4484352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4485352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
4486352f7f91STakashi Iwai 		if (err < 0)
4487352f7f91STakashi Iwai 			return err;
4488352f7f91STakashi Iwai 		if (!spec->no_analog) {
4489352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
4490352f7f91STakashi Iwai 							    &spec->multiout);
4491352f7f91STakashi Iwai 			if (err < 0)
4492352f7f91STakashi Iwai 				return err;
4493352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
4494352f7f91STakashi Iwai 		}
4495352f7f91STakashi Iwai 	}
4496352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
4497352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
4498352f7f91STakashi Iwai 		if (err < 0)
4499352f7f91STakashi Iwai 			return err;
4500352f7f91STakashi Iwai 	}
4501352f7f91STakashi Iwai 
4502352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
4503352f7f91STakashi Iwai 	if (!spec->no_analog &&
4504352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
4505352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
45067a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
4507352f7f91STakashi Iwai 					  "Playback Volume");
4508352f7f91STakashi Iwai 		if (err < 0)
4509352f7f91STakashi Iwai 			return err;
4510352f7f91STakashi Iwai 	}
4511352f7f91STakashi Iwai 	if (!spec->no_analog &&
4512352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
4513352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
4514352f7f91STakashi Iwai 					    NULL, slave_pfxs,
4515352f7f91STakashi Iwai 					    "Playback Switch",
4516352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
4517352f7f91STakashi Iwai 		if (err < 0)
4518352f7f91STakashi Iwai 			return err;
4519b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
4520fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
4521fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
4522b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4523b63eae0aSTakashi Iwai 		}
4524352f7f91STakashi Iwai 	}
4525352f7f91STakashi Iwai 
4526352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
4527352f7f91STakashi Iwai 
4528352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
4529352f7f91STakashi Iwai 	if (err < 0)
4530352f7f91STakashi Iwai 		return err;
4531352f7f91STakashi Iwai 
4532352f7f91STakashi Iwai 	return 0;
4533352f7f91STakashi Iwai }
4534352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
4535352f7f91STakashi Iwai 
4536352f7f91STakashi Iwai 
4537352f7f91STakashi Iwai /*
4538352f7f91STakashi Iwai  * PCM definitions
4539352f7f91STakashi Iwai  */
4540352f7f91STakashi Iwai 
4541e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
4542e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
4543e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
4544e6b85f3cSTakashi Iwai 				   int action)
4545e6b85f3cSTakashi Iwai {
4546e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4547e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
4548e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
4549e6b85f3cSTakashi Iwai }
4550e6b85f3cSTakashi Iwai 
4551ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
4552ac2e8736STakashi Iwai 				  struct hda_codec *codec,
4553ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
4554ac2e8736STakashi Iwai 				  int action)
4555ac2e8736STakashi Iwai {
4556ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4557ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
4558ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
4559ac2e8736STakashi Iwai }
4560ac2e8736STakashi Iwai 
4561352f7f91STakashi Iwai /*
4562352f7f91STakashi Iwai  * Analog playback callbacks
4563352f7f91STakashi Iwai  */
4564352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
4565352f7f91STakashi Iwai 			     struct hda_codec *codec,
4566352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
4567352f7f91STakashi Iwai {
4568352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
456938cf6f1aSTakashi Iwai 	int err;
457038cf6f1aSTakashi Iwai 
457138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
457238cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
457338cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
4574352f7f91STakashi Iwai 					     hinfo);
4575e6b85f3cSTakashi Iwai 	if (!err) {
457638cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
4577e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4578e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
4579e6b85f3cSTakashi Iwai 	}
458038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
458138cf6f1aSTakashi Iwai 	return err;
4582352f7f91STakashi Iwai }
4583352f7f91STakashi Iwai 
4584352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
458597ec558aSTakashi Iwai 				struct hda_codec *codec,
458697ec558aSTakashi Iwai 				unsigned int stream_tag,
458797ec558aSTakashi Iwai 				unsigned int format,
458897ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
458997ec558aSTakashi Iwai {
4590352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4591e6b85f3cSTakashi Iwai 	int err;
4592e6b85f3cSTakashi Iwai 
4593e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4594352f7f91STakashi Iwai 					       stream_tag, format, substream);
4595e6b85f3cSTakashi Iwai 	if (!err)
4596e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4597e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4598e6b85f3cSTakashi Iwai 	return err;
4599352f7f91STakashi Iwai }
460097ec558aSTakashi Iwai 
4601352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4602352f7f91STakashi Iwai 				struct hda_codec *codec,
4603352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4604352f7f91STakashi Iwai {
4605352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4606e6b85f3cSTakashi Iwai 	int err;
4607e6b85f3cSTakashi Iwai 
4608e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4609e6b85f3cSTakashi Iwai 	if (!err)
4610e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4611e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4612e6b85f3cSTakashi Iwai 	return err;
4613352f7f91STakashi Iwai }
4614352f7f91STakashi Iwai 
461538cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
461638cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
461738cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
461838cf6f1aSTakashi Iwai {
461938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
462038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
462138cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4622e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4623e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
462438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
462538cf6f1aSTakashi Iwai 	return 0;
462638cf6f1aSTakashi Iwai }
462738cf6f1aSTakashi Iwai 
4628ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4629ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4630ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4631ac2e8736STakashi Iwai {
4632ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4633ac2e8736STakashi Iwai 	return 0;
4634ac2e8736STakashi Iwai }
4635ac2e8736STakashi Iwai 
4636ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4637ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4638ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4639ac2e8736STakashi Iwai 			       unsigned int format,
4640ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4641ac2e8736STakashi Iwai {
4642ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4643ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4644ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4645ac2e8736STakashi Iwai 	return 0;
4646ac2e8736STakashi Iwai }
4647ac2e8736STakashi Iwai 
4648ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4649ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4650ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4651ac2e8736STakashi Iwai {
4652ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4653ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4654ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4655ac2e8736STakashi Iwai 	return 0;
4656ac2e8736STakashi Iwai }
4657ac2e8736STakashi Iwai 
4658ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4659ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4660ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4661ac2e8736STakashi Iwai {
4662ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4663ac2e8736STakashi Iwai 	return 0;
4664ac2e8736STakashi Iwai }
4665ac2e8736STakashi Iwai 
466638cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
466738cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
466838cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
466938cf6f1aSTakashi Iwai {
467038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
467138cf6f1aSTakashi Iwai 	int err = 0;
467238cf6f1aSTakashi Iwai 
467338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
467438cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
467538cf6f1aSTakashi Iwai 		err = -EBUSY;
467638cf6f1aSTakashi Iwai 	else
467738cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4678e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4679e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
468038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
468138cf6f1aSTakashi Iwai 	return err;
468238cf6f1aSTakashi Iwai }
468338cf6f1aSTakashi Iwai 
468438cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
468538cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
468638cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
468738cf6f1aSTakashi Iwai {
468838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
468938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
469038cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4691e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4692e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
469338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
469438cf6f1aSTakashi Iwai 	return 0;
469538cf6f1aSTakashi Iwai }
469638cf6f1aSTakashi Iwai 
4697e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4698e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4699e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4700e6b85f3cSTakashi Iwai 				    unsigned int format,
4701e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4702e6b85f3cSTakashi Iwai {
4703e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4704e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4705e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4706e6b85f3cSTakashi Iwai 	return 0;
4707e6b85f3cSTakashi Iwai }
4708e6b85f3cSTakashi Iwai 
4709e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4710e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4711e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4712e6b85f3cSTakashi Iwai {
4713e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4714e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4715e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4716e6b85f3cSTakashi Iwai 	return 0;
4717e6b85f3cSTakashi Iwai }
4718e6b85f3cSTakashi Iwai 
4719352f7f91STakashi Iwai /*
4720352f7f91STakashi Iwai  * Digital out
4721352f7f91STakashi Iwai  */
4722352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4723352f7f91STakashi Iwai 				 struct hda_codec *codec,
4724352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4725352f7f91STakashi Iwai {
4726352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4727352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4728352f7f91STakashi Iwai }
4729352f7f91STakashi Iwai 
4730352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4731352f7f91STakashi Iwai 				    struct hda_codec *codec,
4732352f7f91STakashi Iwai 				    unsigned int stream_tag,
4733352f7f91STakashi Iwai 				    unsigned int format,
4734352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4735352f7f91STakashi Iwai {
4736352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4737352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4738352f7f91STakashi Iwai 					     stream_tag, format, substream);
4739352f7f91STakashi Iwai }
4740352f7f91STakashi Iwai 
4741352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4742352f7f91STakashi Iwai 				    struct hda_codec *codec,
4743352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4744352f7f91STakashi Iwai {
4745352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4746352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4747352f7f91STakashi Iwai }
4748352f7f91STakashi Iwai 
4749352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4750352f7f91STakashi Iwai 				  struct hda_codec *codec,
4751352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4752352f7f91STakashi Iwai {
4753352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4754352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4755352f7f91STakashi Iwai }
4756352f7f91STakashi Iwai 
4757352f7f91STakashi Iwai /*
4758352f7f91STakashi Iwai  * Analog capture
4759352f7f91STakashi Iwai  */
4760ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4761ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4762ac2e8736STakashi Iwai 
4763352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4764352f7f91STakashi Iwai 				   struct hda_codec *codec,
4765352f7f91STakashi Iwai 				   unsigned int stream_tag,
4766352f7f91STakashi Iwai 				   unsigned int format,
4767352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4768352f7f91STakashi Iwai {
4769352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4770352f7f91STakashi Iwai 
4771352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
477297ec558aSTakashi Iwai 				   stream_tag, 0, format);
4773ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4774ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
477597ec558aSTakashi Iwai 	return 0;
477697ec558aSTakashi Iwai }
477797ec558aSTakashi Iwai 
4778352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
477997ec558aSTakashi Iwai 				   struct hda_codec *codec,
478097ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
478197ec558aSTakashi Iwai {
4782352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
478397ec558aSTakashi Iwai 
4784352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4785352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4786ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4787ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
478897ec558aSTakashi Iwai 	return 0;
478997ec558aSTakashi Iwai }
479097ec558aSTakashi Iwai 
4791352f7f91STakashi Iwai /*
4792352f7f91STakashi Iwai  */
4793352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4794352f7f91STakashi Iwai 	.substreams = 1,
4795352f7f91STakashi Iwai 	.channels_min = 2,
4796352f7f91STakashi Iwai 	.channels_max = 8,
4797352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4798352f7f91STakashi Iwai 	.ops = {
4799352f7f91STakashi Iwai 		.open = playback_pcm_open,
480038cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4801352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4802352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4803352f7f91STakashi Iwai 	},
4804352f7f91STakashi Iwai };
4805352f7f91STakashi Iwai 
4806352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4807352f7f91STakashi Iwai 	.substreams = 1,
4808352f7f91STakashi Iwai 	.channels_min = 2,
4809352f7f91STakashi Iwai 	.channels_max = 2,
4810352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4811ac2e8736STakashi Iwai 	.ops = {
4812ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4813ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4814ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4815ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4816ac2e8736STakashi Iwai 	},
4817352f7f91STakashi Iwai };
4818352f7f91STakashi Iwai 
4819352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4820352f7f91STakashi Iwai 	.substreams = 1,
4821352f7f91STakashi Iwai 	.channels_min = 2,
4822352f7f91STakashi Iwai 	.channels_max = 2,
4823352f7f91STakashi Iwai 	/* NID is set in build_pcms */
482438cf6f1aSTakashi Iwai 	.ops = {
482538cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4826e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4827e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4828e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
482938cf6f1aSTakashi Iwai 	},
4830352f7f91STakashi Iwai };
4831352f7f91STakashi Iwai 
4832352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4833352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4834352f7f91STakashi Iwai 	.channels_min = 2,
4835352f7f91STakashi Iwai 	.channels_max = 2,
4836352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4837352f7f91STakashi Iwai 	.ops = {
4838ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4839ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4840352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4841352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4842352f7f91STakashi Iwai 	},
4843352f7f91STakashi Iwai };
4844352f7f91STakashi Iwai 
4845352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4846352f7f91STakashi Iwai 	.substreams = 1,
4847352f7f91STakashi Iwai 	.channels_min = 2,
4848352f7f91STakashi Iwai 	.channels_max = 2,
4849352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4850352f7f91STakashi Iwai 	.ops = {
4851352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4852352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4853352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4854352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4855352f7f91STakashi Iwai 	},
4856352f7f91STakashi Iwai };
4857352f7f91STakashi Iwai 
4858352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4859352f7f91STakashi Iwai 	.substreams = 1,
4860352f7f91STakashi Iwai 	.channels_min = 2,
4861352f7f91STakashi Iwai 	.channels_max = 2,
4862352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4863352f7f91STakashi Iwai };
4864352f7f91STakashi Iwai 
4865352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4866352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4867352f7f91STakashi Iwai 	.substreams = 0,
4868352f7f91STakashi Iwai 	.channels_min = 0,
4869352f7f91STakashi Iwai 	.channels_max = 0,
4870352f7f91STakashi Iwai };
4871352f7f91STakashi Iwai 
4872352f7f91STakashi Iwai /*
4873352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4874352f7f91STakashi Iwai  */
4875352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
48761da177e4SLinus Torvalds {
4877352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4878352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
48791da177e4SLinus Torvalds 
4880352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4881352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4882352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4883352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4884352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4885352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4886352f7f91STakashi Iwai 					   spec->cur_adc_format);
4887352f7f91STakashi Iwai 		return true;
4888352f7f91STakashi Iwai 	}
4889352f7f91STakashi Iwai 	return false;
4890352f7f91STakashi Iwai }
4891352f7f91STakashi Iwai 
4892352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4893352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4894352f7f91STakashi Iwai 				       struct hda_codec *codec,
4895352f7f91STakashi Iwai 				       unsigned int stream_tag,
4896352f7f91STakashi Iwai 				       unsigned int format,
4897352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4898352f7f91STakashi Iwai {
4899352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4900352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4901352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4902352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4903352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
49041da177e4SLinus Torvalds 	return 0;
49051da177e4SLinus Torvalds }
49061da177e4SLinus Torvalds 
4907352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4908352f7f91STakashi Iwai 				       struct hda_codec *codec,
4909352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4910352f7f91STakashi Iwai {
4911352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4912352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4913352f7f91STakashi Iwai 	spec->cur_adc = 0;
4914352f7f91STakashi Iwai 	return 0;
4915352f7f91STakashi Iwai }
4916352f7f91STakashi Iwai 
4917352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4918352f7f91STakashi Iwai 	.substreams = 1,
4919352f7f91STakashi Iwai 	.channels_min = 2,
4920352f7f91STakashi Iwai 	.channels_max = 2,
4921352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4922352f7f91STakashi Iwai 	.ops = {
4923352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4924352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4925352f7f91STakashi Iwai 	},
4926352f7f91STakashi Iwai };
4927352f7f91STakashi Iwai 
4928f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4929f873e536STakashi Iwai 				 const char *chip_name)
4930f873e536STakashi Iwai {
4931f873e536STakashi Iwai 	char *p;
4932f873e536STakashi Iwai 
4933f873e536STakashi Iwai 	if (*str)
4934f873e536STakashi Iwai 		return;
4935f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4936f873e536STakashi Iwai 
4937f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4938f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4939f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4940f873e536STakashi Iwai 			*p = 0;
4941f873e536STakashi Iwai 			break;
4942f873e536STakashi Iwai 		}
4943f873e536STakashi Iwai 	}
4944f873e536STakashi Iwai 	strlcat(str, sfx, len);
4945f873e536STakashi Iwai }
4946f873e536STakashi Iwai 
4947352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4948352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4949352f7f91STakashi Iwai {
4950352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4951352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4952352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4953352f7f91STakashi Iwai 	bool have_multi_adcs;
4954352f7f91STakashi Iwai 
49551da177e4SLinus Torvalds 	codec->num_pcms = 1;
49561da177e4SLinus Torvalds 	codec->pcm_info = info;
49571da177e4SLinus Torvalds 
4958352f7f91STakashi Iwai 	if (spec->no_analog)
4959352f7f91STakashi Iwai 		goto skip_analog;
4960352f7f91STakashi Iwai 
4961f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
4962f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
4963f873e536STakashi Iwai 			     " Analog", codec->chip_name);
4964352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
4965352f7f91STakashi Iwai 
4966352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
4967352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
4968352f7f91STakashi Iwai 		if (!p)
4969352f7f91STakashi Iwai 			p = &pcm_analog_playback;
4970352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4971352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4972352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
4973352f7f91STakashi Iwai 			spec->multiout.max_channels;
4974352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
4975352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
4976352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
4977352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
4978352f7f91STakashi Iwai 	}
4979352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
4980352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
4981352f7f91STakashi Iwai 		if (!p) {
4982352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
4983352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
4984352f7f91STakashi Iwai 			else
4985352f7f91STakashi Iwai 				p = &pcm_analog_capture;
4986352f7f91STakashi Iwai 		}
4987352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4988352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4989352f7f91STakashi Iwai 	}
4990352f7f91STakashi Iwai 
4991352f7f91STakashi Iwai  skip_analog:
4992352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
4993352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4994f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
4995352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
4996f873e536STakashi Iwai 				     " Digital", codec->chip_name);
4997352f7f91STakashi Iwai 		codec->num_pcms = 2;
4998352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4999352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
5000352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
5001352f7f91STakashi Iwai 		if (spec->dig_out_type)
5002352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5003352f7f91STakashi Iwai 		else
5004352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5005352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
5006352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
5007352f7f91STakashi Iwai 			if (!p)
5008352f7f91STakashi Iwai 				p = &pcm_digital_playback;
5009352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5010352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
5011352f7f91STakashi Iwai 		}
5012352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
5013352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
5014352f7f91STakashi Iwai 			if (!p)
5015352f7f91STakashi Iwai 				p = &pcm_digital_capture;
5016352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5017352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
5018352f7f91STakashi Iwai 		}
5019352f7f91STakashi Iwai 	}
5020352f7f91STakashi Iwai 
5021352f7f91STakashi Iwai 	if (spec->no_analog)
5022352f7f91STakashi Iwai 		return 0;
5023352f7f91STakashi Iwai 
5024352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5025352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5026352f7f91STakashi Iwai 	 */
5027352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5028352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5029352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5030352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5031a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5032a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
5033a607148fSTakashi Iwai 			     " Alt Analog", codec->chip_name);
5034352f7f91STakashi Iwai 		codec->num_pcms = 3;
5035352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
5036a607148fSTakashi Iwai 		info->name = spec->stream_name_alt_analog;
5037352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
5038352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
5039352f7f91STakashi Iwai 			if (!p)
5040352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
5041352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5042352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
5043352f7f91STakashi Iwai 				spec->alt_dac_nid;
5044352f7f91STakashi Iwai 		} else {
5045352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
5046352f7f91STakashi Iwai 				pcm_null_stream;
5047352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
5048352f7f91STakashi Iwai 		}
5049352f7f91STakashi Iwai 		if (have_multi_adcs) {
5050352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
5051352f7f91STakashi Iwai 			if (!p)
5052352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
5053352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5054352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
5055352f7f91STakashi Iwai 				spec->adc_nids[1];
5056352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5057352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5058352f7f91STakashi Iwai 		} else {
5059352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
5060352f7f91STakashi Iwai 				pcm_null_stream;
5061352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
5062352f7f91STakashi Iwai 		}
50631da177e4SLinus Torvalds 	}
50641da177e4SLinus Torvalds 
50651da177e4SLinus Torvalds 	return 0;
50661da177e4SLinus Torvalds }
5067352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
5068352f7f91STakashi Iwai 
5069352f7f91STakashi Iwai 
5070352f7f91STakashi Iwai /*
5071352f7f91STakashi Iwai  * Standard auto-parser initializations
5072352f7f91STakashi Iwai  */
5073352f7f91STakashi Iwai 
5074d4156930STakashi Iwai /* configure the given path as a proper output */
50752c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5076352f7f91STakashi Iwai {
5077352f7f91STakashi Iwai 	struct nid_path *path;
5078d4156930STakashi Iwai 	hda_nid_t pin;
5079352f7f91STakashi Iwai 
5080196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5081d4156930STakashi Iwai 	if (!path || !path->depth)
5082352f7f91STakashi Iwai 		return;
5083d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
50842c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
508565033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
508665033cc8STakashi Iwai 			      aamix_default(codec->spec));
5087e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5088352f7f91STakashi Iwai }
5089352f7f91STakashi Iwai 
5090352f7f91STakashi Iwai /* initialize primary output paths */
5091352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5092352f7f91STakashi Iwai {
5093352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5094352f7f91STakashi Iwai 	int i;
5095352f7f91STakashi Iwai 
5096d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
50972c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5098352f7f91STakashi Iwai }
5099352f7f91STakashi Iwai 
5100db23fd19STakashi Iwai 
51012c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5102352f7f91STakashi Iwai {
5103352f7f91STakashi Iwai 	int i;
5104352f7f91STakashi Iwai 
5105d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
51062c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5107352f7f91STakashi Iwai }
5108db23fd19STakashi Iwai 
5109db23fd19STakashi Iwai /* initialize hp and speaker paths */
5110db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5111db23fd19STakashi Iwai {
5112db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5113db23fd19STakashi Iwai 
5114db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
51152c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5116db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5117db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
51182c12c30dSTakashi Iwai 				 spec->speaker_paths);
5119352f7f91STakashi Iwai }
5120352f7f91STakashi Iwai 
5121352f7f91STakashi Iwai /* initialize multi-io paths */
5122352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5123352f7f91STakashi Iwai {
5124352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5125352f7f91STakashi Iwai 	int i;
5126352f7f91STakashi Iwai 
5127352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5128352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5129352f7f91STakashi Iwai 		struct nid_path *path;
5130196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5131352f7f91STakashi Iwai 		if (!path)
5132352f7f91STakashi Iwai 			continue;
5133352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5134352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
51352c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
513665033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
513765033cc8STakashi Iwai 				      aamix_default(spec));
5138352f7f91STakashi Iwai 	}
5139352f7f91STakashi Iwai }
5140352f7f91STakashi Iwai 
5141352f7f91STakashi Iwai /* set up input pins and loopback paths */
5142352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5143352f7f91STakashi Iwai {
5144352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5145352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5146352f7f91STakashi Iwai 	int i;
5147352f7f91STakashi Iwai 
5148352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5149352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5150352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
51512c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5152352f7f91STakashi Iwai 
5153352f7f91STakashi Iwai 		/* init loopback inputs */
5154352f7f91STakashi Iwai 		if (spec->mixer_nid) {
51553e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
51563e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5157352f7f91STakashi Iwai 		}
5158352f7f91STakashi Iwai 	}
5159352f7f91STakashi Iwai }
5160352f7f91STakashi Iwai 
5161352f7f91STakashi Iwai /* initialize ADC paths */
5162352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5163352f7f91STakashi Iwai {
5164352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5165352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5166352f7f91STakashi Iwai 	struct nid_path *path;
5167352f7f91STakashi Iwai 	int i, c, nums;
5168352f7f91STakashi Iwai 
5169352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5170352f7f91STakashi Iwai 		nums = 1;
5171352f7f91STakashi Iwai 	else
5172352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5173352f7f91STakashi Iwai 
5174352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5175352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5176c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5177352f7f91STakashi Iwai 			if (path) {
5178352f7f91STakashi Iwai 				bool active = path->active;
5179352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5180352f7f91STakashi Iwai 					active = true;
5181352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5182352f7f91STakashi Iwai 			}
5183352f7f91STakashi Iwai 		}
5184967303daSTakashi Iwai 		if (spec->hp_mic)
5185967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5186352f7f91STakashi Iwai 	}
5187352f7f91STakashi Iwai 
5188352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
5189a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
5190352f7f91STakashi Iwai }
5191352f7f91STakashi Iwai 
5192352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5193352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5194352f7f91STakashi Iwai {
5195352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5196352f7f91STakashi Iwai 	int i;
5197352f7f91STakashi Iwai 	hda_nid_t pin;
5198352f7f91STakashi Iwai 
5199d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
52002c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5201352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
52022430d7b7STakashi Iwai 	if (pin) {
52032c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
52043e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
52052430d7b7STakashi Iwai 	}
5206352f7f91STakashi Iwai }
5207352f7f91STakashi Iwai 
5208973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5209973e4972STakashi Iwai  * invalid unsol tags by some reason
5210973e4972STakashi Iwai  */
5211973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5212973e4972STakashi Iwai {
5213973e4972STakashi Iwai 	int i;
5214973e4972STakashi Iwai 
5215973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5216973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5217973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5218973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5219973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5220973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5221973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5222973e4972STakashi Iwai 	}
5223973e4972STakashi Iwai }
5224973e4972STakashi Iwai 
52255187ac16STakashi Iwai /*
52265187ac16STakashi Iwai  * initialize the generic spec;
52275187ac16STakashi Iwai  * this can be put as patch_ops.init function
52285187ac16STakashi Iwai  */
5229352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5230352f7f91STakashi Iwai {
5231352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5232352f7f91STakashi Iwai 
5233352f7f91STakashi Iwai 	if (spec->init_hook)
5234352f7f91STakashi Iwai 		spec->init_hook(codec);
5235352f7f91STakashi Iwai 
5236352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5237352f7f91STakashi Iwai 
52383bbcd274STakashi Iwai 	codec->cached_write = 1;
52393bbcd274STakashi Iwai 
5240352f7f91STakashi Iwai 	init_multi_out(codec);
5241352f7f91STakashi Iwai 	init_extra_out(codec);
5242352f7f91STakashi Iwai 	init_multi_io(codec);
5243352f7f91STakashi Iwai 	init_analog_input(codec);
5244352f7f91STakashi Iwai 	init_input_src(codec);
5245352f7f91STakashi Iwai 	init_digital(codec);
5246352f7f91STakashi Iwai 
5247973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5248973e4972STakashi Iwai 
5249352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5250a5cc2509STakashi Iwai 	update_automute_all(codec);
5251352f7f91STakashi Iwai 
5252dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec);
52533bbcd274STakashi Iwai 
5254352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5255352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5256352f7f91STakashi Iwai 
5257352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5258352f7f91STakashi Iwai 	return 0;
5259352f7f91STakashi Iwai }
5260fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
5261fce52a3bSTakashi Iwai 
52625187ac16STakashi Iwai /*
52635187ac16STakashi Iwai  * free the generic spec;
52645187ac16STakashi Iwai  * this can be put as patch_ops.free function
52655187ac16STakashi Iwai  */
5266fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5267fce52a3bSTakashi Iwai {
52687504b6cdSTakashi Iwai 	snd_hda_detach_beep_device(codec);
5269fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5270fce52a3bSTakashi Iwai 	kfree(codec->spec);
5271fce52a3bSTakashi Iwai 	codec->spec = NULL;
5272fce52a3bSTakashi Iwai }
5273fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
5274fce52a3bSTakashi Iwai 
5275fce52a3bSTakashi Iwai #ifdef CONFIG_PM
52765187ac16STakashi Iwai /*
52775187ac16STakashi Iwai  * check the loopback power save state;
52785187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
52795187ac16STakashi Iwai  */
5280fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5281fce52a3bSTakashi Iwai {
5282fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5283fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5284fce52a3bSTakashi Iwai }
5285fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
5286fce52a3bSTakashi Iwai #endif
5287352f7f91STakashi Iwai 
5288352f7f91STakashi Iwai 
5289352f7f91STakashi Iwai /*
5290352f7f91STakashi Iwai  * the generic codec support
5291352f7f91STakashi Iwai  */
52921da177e4SLinus Torvalds 
5293352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5294352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5295352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5296352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5297fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5298352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
529983012a7cSTakashi Iwai #ifdef CONFIG_PM
5300fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5301cb53c626STakashi Iwai #endif
53021da177e4SLinus Torvalds };
53031da177e4SLinus Torvalds 
53041da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
53051da177e4SLinus Torvalds {
5306352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
53071da177e4SLinus Torvalds 	int err;
53081da177e4SLinus Torvalds 
5309e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5310352f7f91STakashi Iwai 	if (!spec)
53111da177e4SLinus Torvalds 		return -ENOMEM;
5312352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
53131da177e4SLinus Torvalds 	codec->spec = spec;
53141da177e4SLinus Torvalds 
53159eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
53169eb413e5STakashi Iwai 	if (err < 0)
53179eb413e5STakashi Iwai 		return err;
53189eb413e5STakashi Iwai 
53199eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5320352f7f91STakashi Iwai 	if (err < 0)
53211da177e4SLinus Torvalds 		goto error;
53221da177e4SLinus Torvalds 
53231da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
53241da177e4SLinus Torvalds 	return 0;
53251da177e4SLinus Torvalds 
53261da177e4SLinus Torvalds error:
5327fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
53281da177e4SLinus Torvalds 	return err;
53291da177e4SLinus Torvalds }
5330fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
5331