xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 3690739b)
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 
4773690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
4783690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
4793690739bSTakashi Iwai {
4803690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4813690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
4823690739bSTakashi Iwai 
4833690739bSTakashi Iwai 	if (!list)
4843690739bSTakashi Iwai 		return 0;
4853690739bSTakashi Iwai 	for (; *list; list += 2)
4863690739bSTakashi Iwai 		if (*list == pin)
4873690739bSTakashi Iwai 			return list[1];
4883690739bSTakashi Iwai 	return 0;
4893690739bSTakashi Iwai }
4903690739bSTakashi Iwai 
491352f7f91STakashi Iwai /* look for an empty DAC slot */
492352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
493352f7f91STakashi Iwai 			      bool is_digital)
494352f7f91STakashi Iwai {
495352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
496352f7f91STakashi Iwai 	bool cap_digital;
497352f7f91STakashi Iwai 	int i;
498352f7f91STakashi Iwai 
499352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
500352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
501352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
502352f7f91STakashi Iwai 			continue;
503352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
504352f7f91STakashi Iwai 		if (is_digital != cap_digital)
505352f7f91STakashi Iwai 			continue;
506352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
507352f7f91STakashi Iwai 			return nid;
508352f7f91STakashi Iwai 	}
509352f7f91STakashi Iwai 	return 0;
510352f7f91STakashi Iwai }
511352f7f91STakashi Iwai 
512352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
513352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
514352f7f91STakashi Iwai {
515352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
516352f7f91STakashi Iwai 	val |= chs << 16;
517352f7f91STakashi Iwai 	return val;
518352f7f91STakashi Iwai }
519352f7f91STakashi Iwai 
520352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
521352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
522352f7f91STakashi Iwai 			   int dir, unsigned int bits)
523352f7f91STakashi Iwai {
524352f7f91STakashi Iwai 	if (!nid)
525352f7f91STakashi Iwai 		return false;
526352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
527352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
528352f7f91STakashi Iwai 			return true;
529352f7f91STakashi Iwai 	return false;
530352f7f91STakashi Iwai }
531352f7f91STakashi Iwai 
53299a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
53399a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
53499a5592dSDavid Henningsson {
53599a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
53699a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
53799a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
53899a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
53999a5592dSDavid Henningsson }
54099a5592dSDavid Henningsson 
541352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
542f69910ddSTakashi Iwai 	check_amp_caps(codec, nid, dir, (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE))
543352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
544352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
545352f7f91STakashi Iwai 
546352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
547352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
548352f7f91STakashi Iwai 				       struct nid_path *path)
549352f7f91STakashi Iwai {
550352f7f91STakashi Iwai 	int i;
551352f7f91STakashi Iwai 
552352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
553352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
554352f7f91STakashi Iwai 			return path->path[i];
555352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
556352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
557352f7f91STakashi Iwai 			return path->path[i];
558352f7f91STakashi Iwai 	}
559352f7f91STakashi Iwai 	return 0;
560352f7f91STakashi Iwai }
561352f7f91STakashi Iwai 
562352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
563352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
564352f7f91STakashi Iwai 				      struct nid_path *path)
565352f7f91STakashi Iwai {
566a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
567352f7f91STakashi Iwai 	int i;
568352f7f91STakashi Iwai 
569352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
570a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
571a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
572a1114a8cSTakashi Iwai 			continue;
573a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
574a1114a8cSTakashi Iwai 			return nid;
575352f7f91STakashi Iwai 	}
576352f7f91STakashi Iwai 	return 0;
577352f7f91STakashi Iwai }
578352f7f91STakashi Iwai 
579352f7f91STakashi Iwai /*
580352f7f91STakashi Iwai  * path activation / deactivation
581352f7f91STakashi Iwai  */
582352f7f91STakashi Iwai 
583352f7f91STakashi Iwai /* can have the amp-in capability? */
584352f7f91STakashi Iwai static bool has_amp_in(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_IN_AMP))
591352f7f91STakashi Iwai 		return false;
592352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
593352f7f91STakashi Iwai 		return false;
594352f7f91STakashi Iwai 	return true;
595352f7f91STakashi Iwai }
596352f7f91STakashi Iwai 
597352f7f91STakashi Iwai /* can have the amp-out capability? */
598352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
599352f7f91STakashi Iwai {
600352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
601352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
602352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
605352f7f91STakashi Iwai 		return false;
606352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
607352f7f91STakashi Iwai 		return false;
608352f7f91STakashi Iwai 	return true;
609352f7f91STakashi Iwai }
610352f7f91STakashi Iwai 
611352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
612352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6137dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
614352f7f91STakashi Iwai {
615352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
616352f7f91STakashi Iwai 	int i, n;
617352f7f91STakashi Iwai 
618352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
619352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
620352f7f91STakashi Iwai 		if (!path->active)
621352f7f91STakashi Iwai 			continue;
622352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
623352f7f91STakashi Iwai 			if (path->path[i] == nid) {
624352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
625352f7f91STakashi Iwai 					return true;
626352f7f91STakashi Iwai 				break;
627352f7f91STakashi Iwai 			}
628352f7f91STakashi Iwai 		}
629352f7f91STakashi Iwai 	}
630352f7f91STakashi Iwai 	return false;
631352f7f91STakashi Iwai }
632352f7f91STakashi Iwai 
633b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
634b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
635b1b9fbd0STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, 0)
636b1b9fbd0STakashi Iwai 
637352f7f91STakashi Iwai /* get the default amp value for the target state */
638352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6398999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
640352f7f91STakashi Iwai {
641352f7f91STakashi Iwai 	unsigned int val = 0;
642352f7f91STakashi Iwai 
643352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
644352f7f91STakashi Iwai 		/* set to 0dB */
645352f7f91STakashi Iwai 		if (enable)
646352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
647352f7f91STakashi Iwai 	}
648f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
649352f7f91STakashi Iwai 		if (!enable)
650352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
651352f7f91STakashi Iwai 	}
652352f7f91STakashi Iwai 	return val;
653352f7f91STakashi Iwai }
654352f7f91STakashi Iwai 
655352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
656352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
657352f7f91STakashi Iwai {
6588999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6598999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
660352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
661352f7f91STakashi Iwai }
662352f7f91STakashi Iwai 
6638999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6648999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
6658999bf0aSTakashi Iwai  */
6668999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
6678999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
6688999bf0aSTakashi Iwai 					   unsigned int caps)
669352f7f91STakashi Iwai {
6708999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
6718999bf0aSTakashi Iwai 
672f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
6738999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
6748999bf0aSTakashi Iwai 			mask &= ~0x80;
6758999bf0aSTakashi Iwai 	}
6768999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
6778999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
6788999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
6798999bf0aSTakashi Iwai 			mask &= ~0x7f;
6808999bf0aSTakashi Iwai 	}
6818999bf0aSTakashi Iwai 	return mask;
6828999bf0aSTakashi Iwai }
6838999bf0aSTakashi Iwai 
6848999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
6858999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
6868999bf0aSTakashi Iwai {
6878999bf0aSTakashi Iwai 	unsigned int caps;
6888999bf0aSTakashi Iwai 	unsigned int mask, val;
6898999bf0aSTakashi Iwai 
6907dddf2aeSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
691352f7f91STakashi Iwai 		return;
6928999bf0aSTakashi Iwai 
6938999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
6948999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
6958999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
6968999bf0aSTakashi Iwai 	if (!mask)
6978999bf0aSTakashi Iwai 		return;
6988999bf0aSTakashi Iwai 
6998999bf0aSTakashi Iwai 	val &= mask;
7008999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
701352f7f91STakashi Iwai }
702352f7f91STakashi Iwai 
703352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
704352f7f91STakashi Iwai 			     int i, bool enable)
705352f7f91STakashi Iwai {
706352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
707352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
7088999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
709352f7f91STakashi Iwai }
710352f7f91STakashi Iwai 
711352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
712352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
713352f7f91STakashi Iwai {
714352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
715ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
716352f7f91STakashi Iwai 	int n, nums, idx;
717352f7f91STakashi Iwai 	int type;
718352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
719352f7f91STakashi Iwai 
720ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
721352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
722352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
723352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
724352f7f91STakashi Iwai 		nums = 1;
725352f7f91STakashi Iwai 		idx = 0;
726352f7f91STakashi Iwai 	} else
727352f7f91STakashi Iwai 		idx = path->idx[i];
728352f7f91STakashi Iwai 
729352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
730352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
731352f7f91STakashi Iwai 
732352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
733352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
734352f7f91STakashi Iwai 	 */
735352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
736e4a395e7STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
737352f7f91STakashi Iwai 			continue;
7388999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
739352f7f91STakashi Iwai 	}
740352f7f91STakashi Iwai }
741352f7f91STakashi Iwai 
742352f7f91STakashi Iwai /* activate or deactivate the given path
743352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
744352f7f91STakashi Iwai  */
745352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
746352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
747352f7f91STakashi Iwai {
74855196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
749352f7f91STakashi Iwai 	int i;
750352f7f91STakashi Iwai 
751352f7f91STakashi Iwai 	if (!enable)
752352f7f91STakashi Iwai 		path->active = false;
753352f7f91STakashi Iwai 
754352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
75555196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
75655196fffSTakashi Iwai 		if (enable && spec->power_down_unused) {
75755196fffSTakashi Iwai 			/* make sure the widget is powered up */
75855196fffSTakashi Iwai 			if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D0))
75955196fffSTakashi Iwai 				snd_hda_codec_write(codec, nid, 0,
76055196fffSTakashi Iwai 						    AC_VERB_SET_POWER_STATE,
76155196fffSTakashi Iwai 						    AC_PWRST_D0);
76255196fffSTakashi Iwai 		}
763352f7f91STakashi Iwai 		if (enable && path->multi[i])
76455196fffSTakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
765352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
766352f7f91STakashi Iwai 					    path->idx[i]);
767352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
768352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
769352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
770352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
771352f7f91STakashi Iwai 	}
772352f7f91STakashi Iwai 
773352f7f91STakashi Iwai 	if (enable)
774352f7f91STakashi Iwai 		path->active = true;
775352f7f91STakashi Iwai }
776352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
777352f7f91STakashi Iwai 
77855196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
77955196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
78055196fffSTakashi Iwai {
78155196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
782868211dbSJiri Slaby 	bool changed = false;
78355196fffSTakashi Iwai 	int i;
78455196fffSTakashi Iwai 
78555196fffSTakashi Iwai 	if (!spec->power_down_unused || path->active)
78655196fffSTakashi Iwai 		return;
78755196fffSTakashi Iwai 
78855196fffSTakashi Iwai 	for (i = 0; i < path->depth; i++) {
78955196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
790b1b9fbd0STakashi Iwai 		if (!snd_hda_check_power_state(codec, nid, AC_PWRST_D3) &&
791b1b9fbd0STakashi Iwai 		    !is_active_nid_for_any(codec, nid)) {
79255196fffSTakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
79355196fffSTakashi Iwai 					    AC_VERB_SET_POWER_STATE,
79455196fffSTakashi Iwai 					    AC_PWRST_D3);
79555196fffSTakashi Iwai 			changed = true;
79655196fffSTakashi Iwai 		}
79755196fffSTakashi Iwai 	}
79855196fffSTakashi Iwai 
79955196fffSTakashi Iwai 	if (changed) {
80055196fffSTakashi Iwai 		msleep(10);
80155196fffSTakashi Iwai 		snd_hda_codec_read(codec, path->path[0], 0,
80255196fffSTakashi Iwai 				   AC_VERB_GET_POWER_STATE, 0);
80355196fffSTakashi Iwai 	}
80455196fffSTakashi Iwai }
80555196fffSTakashi Iwai 
806d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
807d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
808d5a9f1bbSTakashi Iwai {
809d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
810d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
811d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
812d5a9f1bbSTakashi Iwai 		return;
81305909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
81405909d5cSTakashi Iwai 		return;
815468ac413STakashi Iwai 	if (codec->inv_eapd)
816468ac413STakashi Iwai 		enable = !enable;
817d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
818d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
819d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
820d5a9f1bbSTakashi Iwai }
821d5a9f1bbSTakashi Iwai 
8223e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
8233e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
8243e367f15STakashi Iwai {
8253e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
8263e367f15STakashi Iwai 	if (path)
8273e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
8283e367f15STakashi Iwai }
8293e367f15STakashi Iwai 
830352f7f91STakashi Iwai 
831352f7f91STakashi Iwai /*
832352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
833352f7f91STakashi Iwai  */
834352f7f91STakashi Iwai 
8357eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
8367eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
837bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
838bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
8397eebffd3STakashi Iwai 
840352f7f91STakashi Iwai enum {
841352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
842352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
843352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
844352f7f91STakashi Iwai };
845352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
846352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
8477eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
8487eebffd3STakashi Iwai 	{
8497eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8507eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
8517eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
8527eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
8537eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
8547eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
8557eebffd3STakashi Iwai 	},
856bc2eee29STakashi Iwai 	{
857bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
858bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
859bc2eee29STakashi Iwai 		.get = snd_hda_mixer_bind_switch_get,
860bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
861bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
862bc2eee29STakashi Iwai 	},
863352f7f91STakashi Iwai };
864352f7f91STakashi Iwai 
865352f7f91STakashi Iwai /* add dynamic controls from template */
866a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
867a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
868352f7f91STakashi Iwai 		       int cidx, unsigned long val)
869352f7f91STakashi Iwai {
870352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
871352f7f91STakashi Iwai 
87212c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
873352f7f91STakashi Iwai 	if (!knew)
874a35bd1e3STakashi Iwai 		return NULL;
875352f7f91STakashi Iwai 	knew->index = cidx;
876352f7f91STakashi Iwai 	if (get_amp_nid_(val))
877352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
878352f7f91STakashi Iwai 	knew->private_value = val;
879a35bd1e3STakashi Iwai 	return knew;
880352f7f91STakashi Iwai }
881352f7f91STakashi Iwai 
882352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
883352f7f91STakashi Iwai 				const char *pfx, const char *dir,
884352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
885352f7f91STakashi Iwai {
886975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
887352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
888a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
889a35bd1e3STakashi Iwai 		return -ENOMEM;
890a35bd1e3STakashi Iwai 	return 0;
891352f7f91STakashi Iwai }
892352f7f91STakashi Iwai 
893352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
894352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
895352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
896352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
897352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
898352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
899352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
900352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
901352f7f91STakashi Iwai 
902352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
903352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
904352f7f91STakashi Iwai {
905352f7f91STakashi Iwai 	unsigned int val;
906352f7f91STakashi Iwai 	if (!path)
907352f7f91STakashi Iwai 		return 0;
908352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
909352f7f91STakashi Iwai 	if (!val)
910352f7f91STakashi Iwai 		return 0;
911352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
912352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
913352f7f91STakashi Iwai }
914352f7f91STakashi Iwai 
915352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
916352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
917352f7f91STakashi Iwai 			       int type)
918352f7f91STakashi Iwai {
919352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
920352f7f91STakashi Iwai 	if (path) {
921352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
922352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
923352f7f91STakashi Iwai 			chs = 3; /* stereo */
924352f7f91STakashi Iwai 	}
925352f7f91STakashi Iwai 	return chs;
926352f7f91STakashi Iwai }
927352f7f91STakashi Iwai 
928352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
929352f7f91STakashi Iwai 			  struct nid_path *path)
930352f7f91STakashi Iwai {
931352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
932352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
933352f7f91STakashi Iwai }
934352f7f91STakashi Iwai 
935352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
936352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
937352f7f91STakashi Iwai  */
938352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
939352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
940352f7f91STakashi Iwai {
941352f7f91STakashi Iwai 	unsigned int val;
942352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
943352f7f91STakashi Iwai 
944352f7f91STakashi Iwai 	if (!path)
945352f7f91STakashi Iwai 		return 0;
946352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
947352f7f91STakashi Iwai 	if (!val)
948352f7f91STakashi Iwai 		return 0;
949352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
950352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
951352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
952352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
953352f7f91STakashi Iwai 		if (nums > 1) {
954352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
955352f7f91STakashi Iwai 			val |= nums << 19;
956352f7f91STakashi Iwai 		}
957352f7f91STakashi Iwai 	}
958352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
959352f7f91STakashi Iwai }
960352f7f91STakashi Iwai 
961352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
962352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
963352f7f91STakashi Iwai {
964352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
965352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
966352f7f91STakashi Iwai }
967352f7f91STakashi Iwai 
9687eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
969bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
9707eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
9717eebffd3STakashi Iwai {
9727eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
9737eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
9747eebffd3STakashi Iwai 
9757eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
9767eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
9777eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
9787eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
9797eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
9807eebffd3STakashi Iwai 	}
981bc2eee29STakashi Iwai }
9827eebffd3STakashi Iwai 
983bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
984bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
985bc2eee29STakashi Iwai {
986bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
9877eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
9887eebffd3STakashi Iwai }
9897eebffd3STakashi Iwai 
990bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
991bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
992bc2eee29STakashi Iwai {
993bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
994bc2eee29STakashi Iwai 	return snd_hda_mixer_bind_switch_put(kcontrol, ucontrol);
995bc2eee29STakashi Iwai }
996bc2eee29STakashi Iwai 
997247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
998247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
999247d85eeSTakashi Iwai {
1000247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1001247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1002247d85eeSTakashi Iwai }
1003247d85eeSTakashi Iwai 
1004352f7f91STakashi Iwai static const char * const channel_name[4] = {
1005352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1006352f7f91STakashi Iwai };
1007352f7f91STakashi Iwai 
1008352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1009247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1010247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1011352f7f91STakashi Iwai {
1012247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1013352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1014352f7f91STakashi Iwai 
1015352f7f91STakashi Iwai 	*index = 0;
1016352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1017247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1018352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1019352f7f91STakashi Iwai 
1020352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1021352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1022352f7f91STakashi Iwai 	 */
1023352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1024352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1025352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1026352f7f91STakashi Iwai 
1027247d85eeSTakashi Iwai 	/* multi-io channels */
1028247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1029247d85eeSTakashi Iwai 		return channel_name[ch];
1030247d85eeSTakashi Iwai 
1031352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1032352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1033247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1034247d85eeSTakashi Iwai 		 * don't name it as Speaker
1035247d85eeSTakashi Iwai 		 */
1036247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1037247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1038247d85eeSTakashi Iwai 			break;
1039352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1040352f7f91STakashi Iwai 			return "Speaker";
1041352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1042352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1043352f7f91STakashi Iwai 		break;
1044352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1045247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1046247d85eeSTakashi Iwai 		 * don't name it as Headphone
1047247d85eeSTakashi Iwai 		 */
1048247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1049247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1050247d85eeSTakashi Iwai 			break;
1051352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1052352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1053352f7f91STakashi Iwai 			break;
1054352f7f91STakashi Iwai 		*index = ch;
1055352f7f91STakashi Iwai 		return "Headphone";
1056247d85eeSTakashi Iwai 	}
1057247d85eeSTakashi Iwai 
1058247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1059352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
1060352f7f91STakashi Iwai 		return "PCM";
1061247d85eeSTakashi Iwai 
1062352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1063352f7f91STakashi Iwai 		snd_BUG();
1064352f7f91STakashi Iwai 		return "PCM";
1065352f7f91STakashi Iwai 	}
1066352f7f91STakashi Iwai 
1067352f7f91STakashi Iwai 	return channel_name[ch];
1068352f7f91STakashi Iwai }
1069352f7f91STakashi Iwai 
1070352f7f91STakashi Iwai /*
1071352f7f91STakashi Iwai  * Parse output paths
1072352f7f91STakashi Iwai  */
1073352f7f91STakashi Iwai 
1074352f7f91STakashi Iwai /* badness definition */
1075352f7f91STakashi Iwai enum {
1076352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1077352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1078352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1079352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1080352f7f91STakashi Iwai 	/* No possible multi-ios */
10811d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1082352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1083352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1084352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1085352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1086352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1087352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
108855a63d4dSTakashi Iwai 	/* No independent HP possible */
1089bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1090352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1091352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1092352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1093352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1094352f7f91STakashi Iwai 	/* Volume widget is shared */
1095352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1096352f7f91STakashi Iwai };
1097352f7f91STakashi Iwai 
10980e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1099352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1100352f7f91STakashi Iwai  *
1101352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1102352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1103352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1104352f7f91STakashi Iwai  */
11050e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1106352f7f91STakashi Iwai {
1107352f7f91STakashi Iwai 	hda_nid_t nid;
1108352f7f91STakashi Iwai 	unsigned int val;
1109352f7f91STakashi Iwai 	int badness = 0;
1110352f7f91STakashi Iwai 
1111352f7f91STakashi Iwai 	if (!path)
1112352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
11130e614dd0STakashi Iwai 
11140e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
11150e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
11160e614dd0STakashi Iwai 		return 0; /* already evaluated */
11170e614dd0STakashi Iwai 
1118352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1119352f7f91STakashi Iwai 	if (nid) {
1120352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1121352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1122352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1123352f7f91STakashi Iwai 		else
1124352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1125352f7f91STakashi Iwai 	} else
1126352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1127352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1128352f7f91STakashi Iwai 	if (nid) {
1129352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1130352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1131352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1132352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1133352f7f91STakashi Iwai 		else
1134352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1135352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1136352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1137352f7f91STakashi Iwai 		else
1138352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1139352f7f91STakashi Iwai 	} else
1140352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1141352f7f91STakashi Iwai 	return badness;
1142352f7f91STakashi Iwai }
1143352f7f91STakashi Iwai 
114498bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1145352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1146352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1147352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1148352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1149352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1150352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1151352f7f91STakashi Iwai };
115298bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_main_out_badness);
1153352f7f91STakashi Iwai 
115498bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1155352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1156352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1157352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1158352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1159352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1160352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1161352f7f91STakashi Iwai };
116298bd1115STakashi Iwai EXPORT_SYMBOL_HDA(hda_extra_out_badness);
1163352f7f91STakashi Iwai 
11647385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
11657385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
11667385df61STakashi Iwai {
11677385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
11687385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
11697385df61STakashi Iwai 
11707385df61STakashi Iwai 	if (cfg->line_outs > idx)
11717385df61STakashi Iwai 		return spec->private_dac_nids[idx];
11727385df61STakashi Iwai 	idx -= cfg->line_outs;
11737385df61STakashi Iwai 	if (spec->multi_ios > idx)
11747385df61STakashi Iwai 		return spec->multi_io[idx].dac;
11757385df61STakashi Iwai 	return 0;
11767385df61STakashi Iwai }
11777385df61STakashi Iwai 
11787385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
11797385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
11807385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
11817385df61STakashi Iwai {
11827385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
11837385df61STakashi Iwai }
11847385df61STakashi Iwai 
1185352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1186352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1187352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1188196c1766STakashi Iwai 			   int *path_idx,
1189352f7f91STakashi Iwai 			   const struct badness_table *bad)
1190352f7f91STakashi Iwai {
1191352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1192352f7f91STakashi Iwai 	int i, j;
1193352f7f91STakashi Iwai 	int badness = 0;
1194352f7f91STakashi Iwai 	hda_nid_t dac;
1195352f7f91STakashi Iwai 
1196352f7f91STakashi Iwai 	if (!num_outs)
1197352f7f91STakashi Iwai 		return 0;
1198352f7f91STakashi Iwai 
1199352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
12000c8c0f56STakashi Iwai 		struct nid_path *path;
1201352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
12021e0b5286STakashi Iwai 
12030e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
12040e614dd0STakashi Iwai 		if (path) {
12050e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
12061e0b5286STakashi Iwai 			continue;
12071e0b5286STakashi Iwai 		}
12081e0b5286STakashi Iwai 
12093690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
12103690739bSTakashi Iwai 		if (dacs[i]) {
12113690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
12123690739bSTakashi Iwai 				badness += bad->shared_primary;
12133690739bSTakashi Iwai 		}
12143690739bSTakashi Iwai 
12153690739bSTakashi Iwai 		if (!dacs[i])
1216352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1217352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1218980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1219352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1220352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1221352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1222352f7f91STakashi Iwai 					dacs[j] = 0;
1223980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1224196c1766STakashi Iwai 					path_idx[j] = 0;
1225352f7f91STakashi Iwai 					break;
1226352f7f91STakashi Iwai 				}
1227352f7f91STakashi Iwai 			}
1228352f7f91STakashi Iwai 		}
1229352f7f91STakashi Iwai 		dac = dacs[i];
1230352f7f91STakashi Iwai 		if (!dac) {
12317385df61STakashi Iwai 			if (num_outs > 2)
12327385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
12337385df61STakashi Iwai 			if (!dac)
12347385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
12357385df61STakashi Iwai 			if (!dac)
12367385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1237352f7f91STakashi Iwai 			if (dac) {
1238352f7f91STakashi Iwai 				if (!i)
1239352f7f91STakashi Iwai 					badness += bad->shared_primary;
1240352f7f91STakashi Iwai 				else if (i == 1)
1241352f7f91STakashi Iwai 					badness += bad->shared_surr;
1242352f7f91STakashi Iwai 				else
1243352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1244352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1245352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1246352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1247352f7f91STakashi Iwai 			} else if (!i)
1248352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1249352f7f91STakashi Iwai 			else
1250352f7f91STakashi Iwai 				badness += bad->no_dac;
1251352f7f91STakashi Iwai 		}
12521fa335b0STakashi Iwai 		if (!dac)
12531fa335b0STakashi Iwai 			continue;
12543ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1255117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1256b3a8c745STakashi Iwai 			/* try with aamix */
12573ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1258b3a8c745STakashi Iwai 		}
12591fa335b0STakashi Iwai 		if (!path) {
1260352f7f91STakashi Iwai 			dac = dacs[i] = 0;
12611fa335b0STakashi Iwai 			badness += bad->no_dac;
12621fa335b0STakashi Iwai 		} else {
1263a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1264e1284af7STakashi Iwai 			path->active = true;
1265196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
12660e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1267e1284af7STakashi Iwai 		}
1268352f7f91STakashi Iwai 	}
1269352f7f91STakashi Iwai 
1270352f7f91STakashi Iwai 	return badness;
1271352f7f91STakashi Iwai }
1272352f7f91STakashi Iwai 
1273352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1274352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1275352f7f91STakashi Iwai {
1276352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1277352f7f91STakashi Iwai 	int i;
1278352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1279352f7f91STakashi Iwai 
1280352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1281352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1282352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1283352f7f91STakashi Iwai 			continue;
1284352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1285352f7f91STakashi Iwai 			if (nid_found)
1286352f7f91STakashi Iwai 				return 0;
1287352f7f91STakashi Iwai 			nid_found = nid;
1288352f7f91STakashi Iwai 		}
1289352f7f91STakashi Iwai 	}
1290352f7f91STakashi Iwai 	return nid_found;
1291352f7f91STakashi Iwai }
1292352f7f91STakashi Iwai 
1293352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1294352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1295352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1296352f7f91STakashi Iwai {
1297352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1298352f7f91STakashi Iwai 
1299352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1300352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1301352f7f91STakashi Iwai 		return false;
1302352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1303352f7f91STakashi Iwai 		return false;
1304352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1305352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1306352f7f91STakashi Iwai 		return false;
1307352f7f91STakashi Iwai 	return true;
1308352f7f91STakashi Iwai }
1309352f7f91STakashi Iwai 
1310e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1311e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1312e22aab7dSTakashi Iwai {
1313e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1314e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1315e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1316e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1317e22aab7dSTakashi Iwai 	int type, i;
1318e22aab7dSTakashi Iwai 	int num_pins = 0;
1319e22aab7dSTakashi Iwai 
1320e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1321e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1322e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1323e22aab7dSTakashi Iwai 				continue;
1324e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1325e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1326e22aab7dSTakashi Iwai 				num_pins++;
1327e22aab7dSTakashi Iwai 		}
1328e22aab7dSTakashi Iwai 	}
1329e22aab7dSTakashi Iwai 	return num_pins;
1330e22aab7dSTakashi Iwai }
1331e22aab7dSTakashi Iwai 
1332352f7f91STakashi Iwai /*
1333352f7f91STakashi Iwai  * multi-io helper
1334352f7f91STakashi Iwai  *
1335352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1336352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1337352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1338352f7f91STakashi Iwai  * the badness value.
1339352f7f91STakashi Iwai  */
1340352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1341352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1342e22aab7dSTakashi Iwai 			  bool hardwired)
1343352f7f91STakashi Iwai {
1344352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1345352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1346e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1347352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1348352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1349352f7f91STakashi Iwai 	int badness = 0;
13500e614dd0STakashi Iwai 	struct nid_path *path;
1351352f7f91STakashi Iwai 
1352352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1353352f7f91STakashi Iwai 	if (old_pins >= 2)
1354352f7f91STakashi Iwai 		goto end_fill;
1355352f7f91STakashi Iwai 
1356e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1357352f7f91STakashi Iwai 	if (num_pins < 2)
1358352f7f91STakashi Iwai 		goto end_fill;
1359352f7f91STakashi Iwai 
1360352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1361352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1362352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1363352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1364352f7f91STakashi Iwai 
1365352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1366352f7f91STakashi Iwai 				continue;
1367352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1368352f7f91STakashi Iwai 				continue;
1369352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1370352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1371352f7f91STakashi Iwai 					break;
1372352f7f91STakashi Iwai 			}
1373352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1374352f7f91STakashi Iwai 				continue;
1375352f7f91STakashi Iwai 
1376352f7f91STakashi Iwai 			if (hardwired)
1377352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1378352f7f91STakashi Iwai 			else if (!dac)
1379352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1380352f7f91STakashi Iwai 			if (!dac) {
1381352f7f91STakashi Iwai 				badness++;
1382352f7f91STakashi Iwai 				continue;
1383352f7f91STakashi Iwai 			}
13843ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
13853ca529d3STakashi Iwai 						    -spec->mixer_nid);
13860c8c0f56STakashi Iwai 			if (!path) {
1387352f7f91STakashi Iwai 				badness++;
1388352f7f91STakashi Iwai 				continue;
1389352f7f91STakashi Iwai 			}
1390a769409cSTakashi Iwai 			/* print_nid_path("multiio", path); */
1391352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1392352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1393196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1394196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1395352f7f91STakashi Iwai 			spec->multi_ios++;
1396352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1397352f7f91STakashi Iwai 				break;
1398352f7f91STakashi Iwai 		}
1399352f7f91STakashi Iwai 	}
1400352f7f91STakashi Iwai  end_fill:
1401352f7f91STakashi Iwai 	if (badness)
1402352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1403352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1404352f7f91STakashi Iwai 		if (hardwired)
1405352f7f91STakashi Iwai 			return 1; /* nothing found */
1406352f7f91STakashi Iwai 		else
1407352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1408352f7f91STakashi Iwai 	}
1409352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1410352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1411352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1412352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1413352f7f91STakashi Iwai 		return badness;
1414352f7f91STakashi Iwai 	}
1415352f7f91STakashi Iwai 
1416352f7f91STakashi Iwai 	/* assign volume and mute controls */
14170e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
14180e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
14190e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
14200e614dd0STakashi Iwai 	}
1421352f7f91STakashi Iwai 
1422352f7f91STakashi Iwai 	return badness;
1423352f7f91STakashi Iwai }
1424352f7f91STakashi Iwai 
1425352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1426352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1427196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1428352f7f91STakashi Iwai {
1429b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1430352f7f91STakashi Iwai 	int i;
1431352f7f91STakashi Iwai 	bool found = false;
1432352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
14330c8c0f56STakashi Iwai 		struct nid_path *path;
1434352f7f91STakashi Iwai 		hda_nid_t dac;
1435352f7f91STakashi Iwai 		if (dacs[i])
1436352f7f91STakashi Iwai 			continue;
1437352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1438352f7f91STakashi Iwai 		if (!dac)
1439352f7f91STakashi Iwai 			continue;
14403ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
14413ca529d3STakashi Iwai 					    -spec->mixer_nid);
1442117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
14433ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
14440c8c0f56STakashi Iwai 		if (path) {
1445352f7f91STakashi Iwai 			dacs[i] = dac;
1446352f7f91STakashi Iwai 			found = true;
1447a769409cSTakashi Iwai 			/* print_nid_path("output", path); */
1448e1284af7STakashi Iwai 			path->active = true;
1449196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1450352f7f91STakashi Iwai 		}
1451352f7f91STakashi Iwai 	}
1452352f7f91STakashi Iwai 	return found;
1453352f7f91STakashi Iwai }
1454352f7f91STakashi Iwai 
1455c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1456c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1457c30aa7b2STakashi Iwai {
14583ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1459c30aa7b2STakashi Iwai 	struct nid_path *path;
14605ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1461c30aa7b2STakashi Iwai 
1462c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
14633ca529d3STakashi Iwai 	if (!path || !path->depth ||
14643ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1465c30aa7b2STakashi Iwai 		return 0;
14665ead56f2STakashi Iwai 	path_dac = path->path[0];
14675ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1468f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1469f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1470f87498b6STakashi Iwai 	if (!path) {
14715ead56f2STakashi Iwai 		if (dac != path_dac)
14725ead56f2STakashi Iwai 			dac = path_dac;
1473f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1474f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1475f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1476f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
14775ead56f2STakashi Iwai 		else
14785ead56f2STakashi Iwai 			dac = 0;
1479f87498b6STakashi Iwai 		if (dac)
1480f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
14813ca529d3STakashi Iwai 						    spec->mixer_nid);
1482f87498b6STakashi Iwai 	}
1483c30aa7b2STakashi Iwai 	if (!path)
1484c30aa7b2STakashi Iwai 		return 0;
1485a769409cSTakashi Iwai 	/* print_nid_path("output-aamix", path); */
1486c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1487c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1488c30aa7b2STakashi Iwai }
1489c30aa7b2STakashi Iwai 
149055a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
149155a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
149255a63d4dSTakashi Iwai {
149355a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
149455a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
149555a63d4dSTakashi Iwai 	struct nid_path *path;
149655a63d4dSTakashi Iwai 	int i, idx;
149755a63d4dSTakashi Iwai 
149855a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
149955a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
150055a63d4dSTakashi Iwai 	else
150155a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
150255a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
150355a63d4dSTakashi Iwai 	if (!path)
150455a63d4dSTakashi Iwai 		return false;
150555a63d4dSTakashi Iwai 
150655a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
150755a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
150855a63d4dSTakashi Iwai 		return true;
150955a63d4dSTakashi Iwai 
151055a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
151155a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
151255a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
151355a63d4dSTakashi Iwai 			break;
151455a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
151555a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
151655a63d4dSTakashi Iwai 			return false;
151755a63d4dSTakashi Iwai 	}
151855a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
151955a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
152055a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
152155a63d4dSTakashi Iwai 			return false;
152255a63d4dSTakashi Iwai 	}
152355a63d4dSTakashi Iwai 
152455a63d4dSTakashi Iwai 	return true;
152555a63d4dSTakashi Iwai }
152655a63d4dSTakashi Iwai 
1527a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1528a07a949bSTakashi Iwai  * shared dac pointed by the paths
1529a07a949bSTakashi Iwai  */
1530a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1531a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1532a07a949bSTakashi Iwai {
1533a07a949bSTakashi Iwai 	struct nid_path *path;
1534a07a949bSTakashi Iwai 	int i;
1535a07a949bSTakashi Iwai 
1536a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1537a07a949bSTakashi Iwai 		if (dacs[i])
1538a07a949bSTakashi Iwai 			continue;
1539a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1540a07a949bSTakashi Iwai 		if (!path)
1541a07a949bSTakashi Iwai 			continue;
1542a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1543a07a949bSTakashi Iwai 	}
1544a07a949bSTakashi Iwai }
1545a07a949bSTakashi Iwai 
1546352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1547352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1548352f7f91STakashi Iwai 			      bool fill_hardwired,
1549352f7f91STakashi Iwai 			      bool fill_mio_first)
1550352f7f91STakashi Iwai {
1551352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1552352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1553352f7f91STakashi Iwai 	int i, err, badness;
1554352f7f91STakashi Iwai 
1555352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1556352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1557352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1558352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1559352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1560352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1561352f7f91STakashi Iwai 	spec->multi_ios = 0;
1562352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1563cd5be3f9STakashi Iwai 
1564cd5be3f9STakashi Iwai 	/* clear path indices */
1565cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1566cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1567cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1568cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1569cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1570c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1571cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1572cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1573cd5be3f9STakashi Iwai 
1574352f7f91STakashi Iwai 	badness = 0;
1575352f7f91STakashi Iwai 
1576352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1577352f7f91STakashi Iwai 	if (fill_hardwired) {
1578352f7f91STakashi Iwai 		bool mapped;
1579352f7f91STakashi Iwai 		do {
1580352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1581352f7f91STakashi Iwai 					     cfg->line_out_pins,
1582196c1766STakashi Iwai 					     spec->private_dac_nids,
1583196c1766STakashi Iwai 					     spec->out_paths);
1584352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1585352f7f91STakashi Iwai 					      cfg->hp_pins,
1586196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1587196c1766STakashi Iwai 					      spec->hp_paths);
1588352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1589352f7f91STakashi Iwai 					      cfg->speaker_pins,
1590196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1591196c1766STakashi Iwai 					      spec->speaker_paths);
1592da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1593da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1594352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1595e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1596352f7f91STakashi Iwai 				if (!err)
1597352f7f91STakashi Iwai 					mapped = true;
1598352f7f91STakashi Iwai 			}
1599352f7f91STakashi Iwai 		} while (mapped);
1600352f7f91STakashi Iwai 	}
1601352f7f91STakashi Iwai 
1602352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1603196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
160498bd1115STakashi Iwai 				   spec->main_out_badness);
1605352f7f91STakashi Iwai 
1606da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1607352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1608352f7f91STakashi Iwai 		/* try to fill multi-io first */
1609e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1610352f7f91STakashi Iwai 		if (err < 0)
1611352f7f91STakashi Iwai 			return err;
1612352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1613352f7f91STakashi Iwai 	}
1614352f7f91STakashi Iwai 
1615352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1616352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1617352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1618196c1766STakashi Iwai 				      spec->hp_paths,
161998bd1115STakashi Iwai 				      spec->extra_out_badness);
1620352f7f91STakashi Iwai 		if (err < 0)
1621352f7f91STakashi Iwai 			return err;
1622352f7f91STakashi Iwai 		badness += err;
1623352f7f91STakashi Iwai 	}
1624352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1625352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1626352f7f91STakashi Iwai 				      cfg->speaker_pins,
1627352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1628196c1766STakashi Iwai 				      spec->speaker_paths,
162998bd1115STakashi Iwai 				      spec->extra_out_badness);
1630352f7f91STakashi Iwai 		if (err < 0)
1631352f7f91STakashi Iwai 			return err;
1632352f7f91STakashi Iwai 		badness += err;
1633352f7f91STakashi Iwai 	}
1634da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1635da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1636e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1637352f7f91STakashi Iwai 		if (err < 0)
1638352f7f91STakashi Iwai 			return err;
1639352f7f91STakashi Iwai 		badness += err;
1640352f7f91STakashi Iwai 	}
1641e22aab7dSTakashi Iwai 
1642c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1643c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1644c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1645c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1646c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1647c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1648c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1649c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1650c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1651c30aa7b2STakashi Iwai 	}
1652c30aa7b2STakashi Iwai 
1653da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1654da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1655e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1656e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1657352f7f91STakashi Iwai 
1658a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1659a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1660a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1661a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1662a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1663a07a949bSTakashi Iwai 		else {
1664a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1665a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1666a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1667a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1668a07a949bSTakashi Iwai 		}
1669a07a949bSTakashi Iwai 	}
1670a07a949bSTakashi Iwai 
1671a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1672c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1673a07a949bSTakashi Iwai 
1674352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1675352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1676352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1677352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1678352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1679352f7f91STakashi Iwai 		spec->multi_ios = 0;
1680352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1681352f7f91STakashi Iwai 	}
1682352f7f91STakashi Iwai 
168355a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
168455a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
168555a63d4dSTakashi Iwai 
1686a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1687a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1688a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1689a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1690a07a949bSTakashi Iwai 				   spec->hp_paths);
1691a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1692a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1693a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1694a07a949bSTakashi Iwai 				   spec->speaker_paths);
1695a07a949bSTakashi Iwai 
1696352f7f91STakashi Iwai 	return badness;
1697352f7f91STakashi Iwai }
1698352f7f91STakashi Iwai 
1699352f7f91STakashi Iwai #define DEBUG_BADNESS
1700352f7f91STakashi Iwai 
1701352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1702352f7f91STakashi Iwai #define debug_badness	snd_printdd
1703352f7f91STakashi Iwai #else
1704352f7f91STakashi Iwai #define debug_badness(...)
1705352f7f91STakashi Iwai #endif
1706352f7f91STakashi Iwai 
1707a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1708a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1709a769409cSTakashi Iwai 				      const char *pfx, int idx)
1710352f7f91STakashi Iwai {
1711a769409cSTakashi Iwai 	struct nid_path *path;
1712a769409cSTakashi Iwai 
1713a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1714a769409cSTakashi Iwai 	if (path)
1715a769409cSTakashi Iwai 		print_nid_path(pfx, path);
1716a769409cSTakashi Iwai }
1717a769409cSTakashi Iwai 
1718a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1719a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1720a769409cSTakashi Iwai {
1721a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1722a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1723a769409cSTakashi Iwai 	int i;
1724a769409cSTakashi Iwai 
1725a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1726352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1727708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1728352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1729352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1730352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1731a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1732a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1733a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1734a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1735352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1736352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1737352f7f91STakashi Iwai 			      spec->multi_ios,
1738352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1739352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1740a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1741a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1742a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1743a769409cSTakashi Iwai 	if (cfg->hp_outs)
1744352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1745352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1746708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1747352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1748352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1749352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1750352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1751a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1752a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1753a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1754352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1755352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1756352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1757352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1758352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1759352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1760352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1761a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1762a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1763a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1764a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1765352f7f91STakashi Iwai }
1766a769409cSTakashi Iwai #else
1767a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1768a769409cSTakashi Iwai #endif
1769352f7f91STakashi Iwai 
1770352f7f91STakashi Iwai /* find all available DACs of the codec */
1771352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1772352f7f91STakashi Iwai {
1773352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1774352f7f91STakashi Iwai 	int i;
1775352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1776352f7f91STakashi Iwai 
1777352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1778352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1779352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1780352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1781352f7f91STakashi Iwai 			continue;
1782352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1783352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1784352f7f91STakashi Iwai 			break;
1785352f7f91STakashi Iwai 		}
1786352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1787352f7f91STakashi Iwai 	}
1788352f7f91STakashi Iwai }
1789352f7f91STakashi Iwai 
1790352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1791352f7f91STakashi Iwai {
1792352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1793352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1794352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
17959314a581STakashi Iwai 	unsigned int val;
1796352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1797352f7f91STakashi Iwai 	int badness;
1798352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1799352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1800352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1801352f7f91STakashi Iwai 
1802352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1803352f7f91STakashi Iwai 	if (!best_cfg)
1804352f7f91STakashi Iwai 		return -ENOMEM;
1805352f7f91STakashi Iwai 	*best_cfg = *cfg;
1806352f7f91STakashi Iwai 
1807352f7f91STakashi Iwai 	for (;;) {
1808352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1809352f7f91STakashi Iwai 					     fill_mio_first);
1810352f7f91STakashi Iwai 		if (badness < 0) {
1811352f7f91STakashi Iwai 			kfree(best_cfg);
1812352f7f91STakashi Iwai 			return badness;
1813352f7f91STakashi Iwai 		}
1814352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1815352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1816352f7f91STakashi Iwai 			      badness);
1817a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1818352f7f91STakashi Iwai 		if (badness < best_badness) {
1819352f7f91STakashi Iwai 			best_badness = badness;
1820352f7f91STakashi Iwai 			*best_cfg = *cfg;
1821352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1822352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1823352f7f91STakashi Iwai 		}
1824352f7f91STakashi Iwai 		if (!badness)
1825352f7f91STakashi Iwai 			break;
1826352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1827352f7f91STakashi Iwai 		if (!fill_mio_first)
1828352f7f91STakashi Iwai 			continue;
1829352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1830352f7f91STakashi Iwai 		if (!fill_hardwired)
1831352f7f91STakashi Iwai 			continue;
1832352f7f91STakashi Iwai 		if (hp_spk_swapped)
1833352f7f91STakashi Iwai 			break;
1834352f7f91STakashi Iwai 		hp_spk_swapped = true;
1835352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1836352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1837352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1838352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1839352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1840352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1841352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1842352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1843352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1844352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1845352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1846352f7f91STakashi Iwai 			fill_hardwired = true;
1847352f7f91STakashi Iwai 			continue;
1848352f7f91STakashi Iwai 		}
1849352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1850352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1851352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1852352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1853352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1854352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1855352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1856352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1857352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1858352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1859352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1860352f7f91STakashi Iwai 			fill_hardwired = true;
1861352f7f91STakashi Iwai 			continue;
1862352f7f91STakashi Iwai 		}
1863352f7f91STakashi Iwai 		break;
1864352f7f91STakashi Iwai 	}
1865352f7f91STakashi Iwai 
1866352f7f91STakashi Iwai 	if (badness) {
18670c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1868352f7f91STakashi Iwai 		*cfg = *best_cfg;
1869352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1870352f7f91STakashi Iwai 	}
1871352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1872352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1873a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
1874352f7f91STakashi Iwai 
1875352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1876352f7f91STakashi Iwai 		struct nid_path *path;
1877196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1878352f7f91STakashi Iwai 		if (path)
1879352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
18807a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
18817a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
18827a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1883352f7f91STakashi Iwai 	}
1884352f7f91STakashi Iwai 
18859314a581STakashi Iwai 	/* set initial pinctl targets */
18869314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
18879314a581STakashi Iwai 		val = PIN_HP;
18889314a581STakashi Iwai 	else
18899314a581STakashi Iwai 		val = PIN_OUT;
18909314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
18919314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
18929314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
18939314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
18949314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
18959314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
18969314a581STakashi Iwai 				cfg->speaker_pins, val);
18979314a581STakashi Iwai 	}
18989314a581STakashi Iwai 
189955a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
190055a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
190155a63d4dSTakashi Iwai 		spec->indep_hp = 0;
190255a63d4dSTakashi Iwai 
1903352f7f91STakashi Iwai 	kfree(best_cfg);
1904352f7f91STakashi Iwai 	return 0;
1905352f7f91STakashi Iwai }
1906352f7f91STakashi Iwai 
1907352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1908352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1909352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1910352f7f91STakashi Iwai {
1911352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1912352f7f91STakashi Iwai 	int i, err, noutputs;
1913352f7f91STakashi Iwai 
1914352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1915352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1916352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1917352f7f91STakashi Iwai 
1918352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1919352f7f91STakashi Iwai 		const char *name;
1920352f7f91STakashi Iwai 		int index;
1921352f7f91STakashi Iwai 		struct nid_path *path;
1922352f7f91STakashi Iwai 
1923196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1924352f7f91STakashi Iwai 		if (!path)
1925352f7f91STakashi Iwai 			continue;
1926247d85eeSTakashi Iwai 
1927247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1928352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1929352f7f91STakashi Iwai 			/* Center/LFE */
1930352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1931352f7f91STakashi Iwai 			if (err < 0)
1932352f7f91STakashi Iwai 				return err;
1933352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1934352f7f91STakashi Iwai 			if (err < 0)
1935352f7f91STakashi Iwai 				return err;
1936247d85eeSTakashi Iwai 		} else {
1937247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1938247d85eeSTakashi Iwai 			if (err < 0)
1939247d85eeSTakashi Iwai 				return err;
1940247d85eeSTakashi Iwai 		}
1941247d85eeSTakashi Iwai 
1942247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1943247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1944352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1945352f7f91STakashi Iwai 			if (err < 0)
1946352f7f91STakashi Iwai 				return err;
1947352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1948352f7f91STakashi Iwai 			if (err < 0)
1949352f7f91STakashi Iwai 				return err;
1950352f7f91STakashi Iwai 		} else {
1951352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1952352f7f91STakashi Iwai 			if (err < 0)
1953352f7f91STakashi Iwai 				return err;
1954352f7f91STakashi Iwai 		}
1955352f7f91STakashi Iwai 	}
1956352f7f91STakashi Iwai 	return 0;
1957352f7f91STakashi Iwai }
1958352f7f91STakashi Iwai 
1959c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1960196c1766STakashi Iwai 			    const char *pfx, int cidx)
1961352f7f91STakashi Iwai {
1962352f7f91STakashi Iwai 	struct nid_path *path;
1963352f7f91STakashi Iwai 	int err;
1964352f7f91STakashi Iwai 
1965196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1966352f7f91STakashi Iwai 	if (!path)
1967352f7f91STakashi Iwai 		return 0;
1968352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1969352f7f91STakashi Iwai 	if (err < 0)
1970352f7f91STakashi Iwai 		return err;
1971352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1972352f7f91STakashi Iwai 	if (err < 0)
1973352f7f91STakashi Iwai 		return err;
1974352f7f91STakashi Iwai 	return 0;
1975352f7f91STakashi Iwai }
1976352f7f91STakashi Iwai 
1977352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1978352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1979196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1980352f7f91STakashi Iwai {
1981c2c80383STakashi Iwai 	int i;
1982352f7f91STakashi Iwai 
1983352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1984c2c80383STakashi Iwai 		const char *name;
1985975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
1986c2c80383STakashi Iwai 		int err, idx = 0;
1987c2c80383STakashi Iwai 
1988c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1989c2c80383STakashi Iwai 			name = "Bass Speaker";
1990c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1991c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1992352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1993c2c80383STakashi Iwai 			name = tmp;
1994352f7f91STakashi Iwai 		} else {
1995c2c80383STakashi Iwai 			name = pfx;
1996c2c80383STakashi Iwai 			idx = i;
1997352f7f91STakashi Iwai 		}
1998c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1999352f7f91STakashi Iwai 		if (err < 0)
2000352f7f91STakashi Iwai 			return err;
2001352f7f91STakashi Iwai 	}
2002352f7f91STakashi Iwai 	return 0;
2003352f7f91STakashi Iwai }
2004352f7f91STakashi Iwai 
2005352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2006352f7f91STakashi Iwai {
2007352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2008352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2009196c1766STakashi Iwai 				 spec->hp_paths,
2010352f7f91STakashi Iwai 				 "Headphone");
2011352f7f91STakashi Iwai }
2012352f7f91STakashi Iwai 
2013352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2014352f7f91STakashi Iwai {
2015352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2016352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2017196c1766STakashi Iwai 				 spec->speaker_paths,
2018352f7f91STakashi Iwai 				 "Speaker");
2019352f7f91STakashi Iwai }
2020352f7f91STakashi Iwai 
2021352f7f91STakashi Iwai /*
202238cf6f1aSTakashi Iwai  * independent HP controls
202338cf6f1aSTakashi Iwai  */
202438cf6f1aSTakashi Iwai 
2025963afde9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack);
202638cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
202738cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
202838cf6f1aSTakashi Iwai {
202938cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
203038cf6f1aSTakashi Iwai }
203138cf6f1aSTakashi Iwai 
203238cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
203338cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
203438cf6f1aSTakashi Iwai {
203538cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
203638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
203738cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
203838cf6f1aSTakashi Iwai 	return 0;
203938cf6f1aSTakashi Iwai }
204038cf6f1aSTakashi Iwai 
2041a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2042a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2043a1e908edSTakashi Iwai 			       int out_type);
2044a1e908edSTakashi Iwai 
204538cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
204638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
204738cf6f1aSTakashi Iwai {
204838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
204938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
205038cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
205138cf6f1aSTakashi Iwai 	int ret = 0;
205238cf6f1aSTakashi Iwai 
205338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
205438cf6f1aSTakashi Iwai 	if (spec->active_streams) {
205538cf6f1aSTakashi Iwai 		ret = -EBUSY;
205638cf6f1aSTakashi Iwai 		goto unlock;
205738cf6f1aSTakashi Iwai 	}
205838cf6f1aSTakashi Iwai 
205938cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2060a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2061a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2062a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2063a1e908edSTakashi Iwai 		else
2064a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2065a1e908edSTakashi Iwai 
2066a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2067a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2068a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2069a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2070a1e908edSTakashi Iwai 						   spec->out_paths[0],
2071a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2072a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2073a1e908edSTakashi Iwai 			else
2074a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2075a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2076a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2077a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2078a1e908edSTakashi Iwai 		}
2079a1e908edSTakashi Iwai 
208038cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
208138cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2082a1e908edSTakashi Iwai 			*dacp = 0;
208338cf6f1aSTakashi Iwai 		else
2084a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
208592603c59STakashi Iwai 
2086963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
208738cf6f1aSTakashi Iwai 		ret = 1;
208838cf6f1aSTakashi Iwai 	}
208938cf6f1aSTakashi Iwai  unlock:
209038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
209138cf6f1aSTakashi Iwai 	return ret;
209238cf6f1aSTakashi Iwai }
209338cf6f1aSTakashi Iwai 
209438cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
209538cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
209638cf6f1aSTakashi Iwai 	.name = "Independent HP",
209738cf6f1aSTakashi Iwai 	.info = indep_hp_info,
209838cf6f1aSTakashi Iwai 	.get = indep_hp_get,
209938cf6f1aSTakashi Iwai 	.put = indep_hp_put,
210038cf6f1aSTakashi Iwai };
210138cf6f1aSTakashi Iwai 
210238cf6f1aSTakashi Iwai 
210338cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
210438cf6f1aSTakashi Iwai {
210538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2106a1e908edSTakashi Iwai 	hda_nid_t dac;
210738cf6f1aSTakashi Iwai 
210838cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
210938cf6f1aSTakashi Iwai 		return 0;
2110a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2111a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2112a1e908edSTakashi Iwai 	else
2113a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2114a1e908edSTakashi Iwai 	if (!dac) {
211538cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
211638cf6f1aSTakashi Iwai 		return 0;
211738cf6f1aSTakashi Iwai 	}
211838cf6f1aSTakashi Iwai 
211938cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2120a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
212138cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
212238cf6f1aSTakashi Iwai 		return -ENOMEM;
212338cf6f1aSTakashi Iwai 	return 0;
212438cf6f1aSTakashi Iwai }
212538cf6f1aSTakashi Iwai 
212638cf6f1aSTakashi Iwai /*
2127352f7f91STakashi Iwai  * channel mode enum control
2128352f7f91STakashi Iwai  */
2129352f7f91STakashi Iwai 
2130352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2131352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2132352f7f91STakashi Iwai {
2133352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2134352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2135a07a949bSTakashi Iwai 	int chs;
2136352f7f91STakashi Iwai 
2137352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2138352f7f91STakashi Iwai 	uinfo->count = 1;
2139352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2140352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2141352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2142a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2143a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2144352f7f91STakashi Iwai 	return 0;
2145352f7f91STakashi Iwai }
2146352f7f91STakashi Iwai 
2147352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2148352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2149352f7f91STakashi Iwai {
2150352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2151352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2152a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2153a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2154352f7f91STakashi Iwai 	return 0;
2155352f7f91STakashi Iwai }
2156352f7f91STakashi Iwai 
2157196c1766STakashi Iwai static inline struct nid_path *
2158196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2159196c1766STakashi Iwai {
2160196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2161196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2162196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2163196c1766STakashi Iwai }
2164196c1766STakashi Iwai 
2165a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2166a5cc2509STakashi Iwai 
216765033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
216865033cc8STakashi Iwai  * used for output paths
216965033cc8STakashi Iwai  */
217065033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
217165033cc8STakashi Iwai {
217265033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
217365033cc8STakashi Iwai }
217465033cc8STakashi Iwai 
2175352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2176352f7f91STakashi Iwai {
2177352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2178352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2179352f7f91STakashi Iwai 	struct nid_path *path;
2180352f7f91STakashi Iwai 
2181196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2182352f7f91STakashi Iwai 	if (!path)
2183352f7f91STakashi Iwai 		return -EINVAL;
2184352f7f91STakashi Iwai 
2185352f7f91STakashi Iwai 	if (path->active == output)
2186352f7f91STakashi Iwai 		return 0;
2187352f7f91STakashi Iwai 
2188352f7f91STakashi Iwai 	if (output) {
21892c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
219065033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2191d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2192352f7f91STakashi Iwai 	} else {
2193d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
219465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
21952c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
219655196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2197352f7f91STakashi Iwai 	}
2198a365fed9STakashi Iwai 
2199a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2200a5cc2509STakashi Iwai 	update_automute_all(codec);
2201a365fed9STakashi Iwai 
2202352f7f91STakashi Iwai 	return 0;
2203352f7f91STakashi Iwai }
2204352f7f91STakashi Iwai 
2205352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2206352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2207352f7f91STakashi Iwai {
2208352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2209352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2210352f7f91STakashi Iwai 	int i, ch;
2211352f7f91STakashi Iwai 
2212352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2213352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2214352f7f91STakashi Iwai 		return -EINVAL;
2215a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2216352f7f91STakashi Iwai 		return 0;
2217a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2218352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2219352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2220352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2221352f7f91STakashi Iwai 					  spec->const_channel_count);
2222352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2223352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2224352f7f91STakashi Iwai 	return 1;
2225352f7f91STakashi Iwai }
2226352f7f91STakashi Iwai 
2227352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2228352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2229352f7f91STakashi Iwai 	.name = "Channel Mode",
2230352f7f91STakashi Iwai 	.info = ch_mode_info,
2231352f7f91STakashi Iwai 	.get = ch_mode_get,
2232352f7f91STakashi Iwai 	.put = ch_mode_put,
2233352f7f91STakashi Iwai };
2234352f7f91STakashi Iwai 
2235352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2236352f7f91STakashi Iwai {
2237352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2238352f7f91STakashi Iwai 
2239352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
224012c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2241352f7f91STakashi Iwai 			return -ENOMEM;
2242352f7f91STakashi Iwai 	}
2243352f7f91STakashi Iwai 	return 0;
2244352f7f91STakashi Iwai }
2245352f7f91STakashi Iwai 
2246352f7f91STakashi Iwai /*
2247c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2248c30aa7b2STakashi Iwai  */
2249c30aa7b2STakashi Iwai 
2250c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2251c30aa7b2STakashi Iwai 
2252c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2253c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2254c30aa7b2STakashi Iwai {
2255c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2256c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2257c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2258c30aa7b2STakashi Iwai 	return 0;
2259c30aa7b2STakashi Iwai }
2260c30aa7b2STakashi Iwai 
2261c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2262a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2263a1e908edSTakashi Iwai 			       int out_type)
2264c30aa7b2STakashi Iwai {
2265a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2266c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2267c30aa7b2STakashi Iwai 
2268c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2269c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2270c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2271c30aa7b2STakashi Iwai 		return;
2272a1e908edSTakashi Iwai 
2273a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2274a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2275a1e908edSTakashi Iwai 	 */
2276a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2277a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2278a1e908edSTakashi Iwai 		do_mix = false;
2279a1e908edSTakashi Iwai 
2280c30aa7b2STakashi Iwai 	if (do_mix) {
2281c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2282c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
228355196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2284c30aa7b2STakashi Iwai 	} else {
228565033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
228665033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
228755196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2288c30aa7b2STakashi Iwai 	}
2289c30aa7b2STakashi Iwai }
2290c30aa7b2STakashi Iwai 
2291c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2292c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2293c30aa7b2STakashi Iwai {
2294c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2295c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2296c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2297c30aa7b2STakashi Iwai 
2298c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2299c30aa7b2STakashi Iwai 		return 0;
2300c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2301c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2302a1e908edSTakashi Iwai 			   spec->aamix_out_paths[0],
2303a1e908edSTakashi Iwai 			   spec->autocfg.line_out_type);
2304c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2305a1e908edSTakashi Iwai 			   spec->aamix_out_paths[1],
2306a1e908edSTakashi Iwai 			   AUTO_PIN_HP_OUT);
2307c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2308a1e908edSTakashi Iwai 			   spec->aamix_out_paths[2],
2309a1e908edSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
2310c30aa7b2STakashi Iwai 	return 1;
2311c30aa7b2STakashi Iwai }
2312c30aa7b2STakashi Iwai 
2313c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2314c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2315c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2316c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2317c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2318c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2319c30aa7b2STakashi Iwai };
2320c30aa7b2STakashi Iwai 
2321c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2322c30aa7b2STakashi Iwai {
2323c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2324c30aa7b2STakashi Iwai 
2325c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2326c30aa7b2STakashi Iwai 		return 0;
2327c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2328c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2329c30aa7b2STakashi Iwai 		return 0;
2330c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2331c30aa7b2STakashi Iwai 		return -ENOMEM;
2332a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2333c30aa7b2STakashi Iwai 	return 0;
2334c30aa7b2STakashi Iwai }
2335c30aa7b2STakashi Iwai 
2336c30aa7b2STakashi Iwai /*
2337352f7f91STakashi Iwai  * shared headphone/mic handling
2338352f7f91STakashi Iwai  */
2339352f7f91STakashi Iwai 
2340352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2341352f7f91STakashi Iwai 
2342352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2343967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2344352f7f91STakashi Iwai {
2345352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2346967303daSTakashi Iwai 	bool as_mic;
2347352f7f91STakashi Iwai 	unsigned int val;
2348967303daSTakashi Iwai 	hda_nid_t pin;
2349967303daSTakashi Iwai 
2350967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2351967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2352967303daSTakashi Iwai 
2353967303daSTakashi Iwai 	if (!force) {
2354967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2355967303daSTakashi Iwai 		if (as_mic) {
2356967303daSTakashi Iwai 			if (val & PIN_IN)
2357967303daSTakashi Iwai 				return;
2358967303daSTakashi Iwai 		} else {
2359967303daSTakashi Iwai 			if (val & PIN_OUT)
2360967303daSTakashi Iwai 				return;
2361967303daSTakashi Iwai 		}
2362967303daSTakashi Iwai 	}
2363352f7f91STakashi Iwai 
2364352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2365967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2366967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2367967303daSTakashi Iwai 	 */
2368352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2369352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2370352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2371352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
23727594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2373967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2374352f7f91STakashi Iwai 	}
2375352f7f91STakashi Iwai 
23768ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2377967303daSTakashi Iwai 		if (as_mic)
2378967303daSTakashi Iwai 			val |= PIN_IN;
2379967303daSTakashi Iwai 		else
2380967303daSTakashi Iwai 			val = PIN_HP;
23812c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2382963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
23838ba955ceSTakashi Iwai 	}
2384352f7f91STakashi Iwai }
2385352f7f91STakashi Iwai 
2386352f7f91STakashi Iwai /* create a shared input with the headphone out */
2387967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2388352f7f91STakashi Iwai {
2389352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2390352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2391352f7f91STakashi Iwai 	unsigned int defcfg;
2392352f7f91STakashi Iwai 	hda_nid_t nid;
2393352f7f91STakashi Iwai 
2394967303daSTakashi Iwai 	if (!spec->hp_mic) {
2395967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2396352f7f91STakashi Iwai 			return 0;
2397967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2398967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2399967303daSTakashi Iwai 		 */
2400967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2401967303daSTakashi Iwai 			return 0;
2402967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2403352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2404352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2405352f7f91STakashi Iwai 				return 0;
2406967303daSTakashi Iwai 		}
2407967303daSTakashi Iwai 	}
2408352f7f91STakashi Iwai 
2409967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2410967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2411967303daSTakashi Iwai 		return 0;
2412967303daSTakashi Iwai 
2413967303daSTakashi Iwai 	nid = 0;
2414967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2415967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2416967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2417967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2418967303daSTakashi Iwai 	if (!nid)
2419967303daSTakashi Iwai 		return 0;
2420352f7f91STakashi Iwai 
2421352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2422352f7f91STakashi Iwai 		return 0; /* no input */
2423352f7f91STakashi Iwai 
2424967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2425967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2426cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2427967303daSTakashi Iwai 	cfg->num_inputs++;
2428967303daSTakashi Iwai 	spec->hp_mic = 1;
2429967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2430967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2431967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
2432352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2433352f7f91STakashi Iwai 	return 0;
2434352f7f91STakashi Iwai }
2435352f7f91STakashi Iwai 
2436978e77e7STakashi Iwai /*
2437978e77e7STakashi Iwai  * output jack mode
2438978e77e7STakashi Iwai  */
24395f171baaSTakashi Iwai 
24405f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
24415f171baaSTakashi Iwai 
24425f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
24435f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
24445f171baaSTakashi Iwai };
24455f171baaSTakashi Iwai 
2446978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2447978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2448978e77e7STakashi Iwai {
24495f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2450978e77e7STakashi Iwai }
2451978e77e7STakashi Iwai 
2452978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2453978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2454978e77e7STakashi Iwai {
2455978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2456978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2457978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2458978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2459978e77e7STakashi Iwai 	else
2460978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2461978e77e7STakashi Iwai 	return 0;
2462978e77e7STakashi Iwai }
2463978e77e7STakashi Iwai 
2464978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2465978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2466978e77e7STakashi Iwai {
2467978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2468978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2469978e77e7STakashi Iwai 	unsigned int val;
2470978e77e7STakashi Iwai 
2471978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2472978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2473978e77e7STakashi Iwai 		return 0;
2474978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2475978e77e7STakashi Iwai 	return 1;
2476978e77e7STakashi Iwai }
2477978e77e7STakashi Iwai 
2478978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2479978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2480978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2481978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2482978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2483978e77e7STakashi Iwai };
2484978e77e7STakashi Iwai 
2485978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2486978e77e7STakashi Iwai {
2487978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2488978e77e7STakashi Iwai 	int i;
2489978e77e7STakashi Iwai 
2490978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2491978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2492978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2493978e77e7STakashi Iwai 			return true;
2494978e77e7STakashi Iwai 	}
2495978e77e7STakashi Iwai 	return false;
2496978e77e7STakashi Iwai }
2497978e77e7STakashi Iwai 
2498978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2499978e77e7STakashi Iwai 			       char *name, size_t name_len)
2500978e77e7STakashi Iwai {
2501978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2502978e77e7STakashi Iwai 	int idx = 0;
2503978e77e7STakashi Iwai 
2504978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2505978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2506978e77e7STakashi Iwai 
2507978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2508978e77e7STakashi Iwai 		;
2509978e77e7STakashi Iwai }
2510978e77e7STakashi Iwai 
25115f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
25125f171baaSTakashi Iwai {
25135f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2514f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
25155f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
25165f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
25175f171baaSTakashi Iwai 			return 2;
25185f171baaSTakashi Iwai 	}
25195f171baaSTakashi Iwai 	return 1;
25205f171baaSTakashi Iwai }
25215f171baaSTakashi Iwai 
2522978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2523978e77e7STakashi Iwai 				 hda_nid_t *pins)
2524978e77e7STakashi Iwai {
2525978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2526978e77e7STakashi Iwai 	int i;
2527978e77e7STakashi Iwai 
2528978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2529978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2530ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
25315f171baaSTakashi Iwai 			continue;
25325f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2533978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2534975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2535978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2536978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2537978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2538978e77e7STakashi Iwai 			if (!knew)
2539978e77e7STakashi Iwai 				return -ENOMEM;
2540978e77e7STakashi Iwai 			knew->private_value = pin;
2541978e77e7STakashi Iwai 		}
2542978e77e7STakashi Iwai 	}
2543978e77e7STakashi Iwai 
2544978e77e7STakashi Iwai 	return 0;
2545978e77e7STakashi Iwai }
2546978e77e7STakashi Iwai 
254729476558STakashi Iwai /*
254829476558STakashi Iwai  * input jack mode
254929476558STakashi Iwai  */
255029476558STakashi Iwai 
255129476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
255229476558STakashi Iwai #define NUM_VREFS	6
255329476558STakashi Iwai 
255429476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
255529476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
255629476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
255729476558STakashi Iwai };
255829476558STakashi Iwai 
255929476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
256029476558STakashi Iwai {
256129476558STakashi Iwai 	unsigned int pincap;
256229476558STakashi Iwai 
256329476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
256429476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
256529476558STakashi Iwai 	/* filter out unusual vrefs */
256629476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
256729476558STakashi Iwai 	return pincap;
256829476558STakashi Iwai }
256929476558STakashi Iwai 
257029476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
257129476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
257229476558STakashi Iwai {
257329476558STakashi Iwai 	unsigned int i, n = 0;
257429476558STakashi Iwai 
257529476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
257629476558STakashi Iwai 		if (vref_caps & (1 << i)) {
257729476558STakashi Iwai 			if (n == item_idx)
257829476558STakashi Iwai 				return i;
257929476558STakashi Iwai 			n++;
258029476558STakashi Iwai 		}
258129476558STakashi Iwai 	}
258229476558STakashi Iwai 	return 0;
258329476558STakashi Iwai }
258429476558STakashi Iwai 
258529476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
258629476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
258729476558STakashi Iwai {
258829476558STakashi Iwai 	unsigned int i, n = 0;
258929476558STakashi Iwai 
259029476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
259129476558STakashi Iwai 		if (i == idx)
259229476558STakashi Iwai 			return n;
259329476558STakashi Iwai 		if (vref_caps & (1 << i))
259429476558STakashi Iwai 			n++;
259529476558STakashi Iwai 	}
259629476558STakashi Iwai 	return 0;
259729476558STakashi Iwai }
259829476558STakashi Iwai 
259929476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
260029476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
260129476558STakashi Iwai {
260229476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
260329476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
260429476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
260529476558STakashi Iwai 
260629476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
260729476558STakashi Iwai 				 vref_texts);
260829476558STakashi Iwai 	/* set the right text */
260929476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
261029476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
261129476558STakashi Iwai 	return 0;
261229476558STakashi Iwai }
261329476558STakashi Iwai 
261429476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
261529476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
261629476558STakashi Iwai {
261729476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
261829476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
261929476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
262029476558STakashi Iwai 	unsigned int idx;
262129476558STakashi Iwai 
262229476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
262329476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
262429476558STakashi Iwai 	return 0;
262529476558STakashi Iwai }
262629476558STakashi Iwai 
262729476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
262829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
262929476558STakashi Iwai {
263029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
263129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
263229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
263329476558STakashi Iwai 	unsigned int val, idx;
263429476558STakashi Iwai 
263529476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
263629476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
263729476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
263829476558STakashi Iwai 		return 0;
263929476558STakashi Iwai 
264029476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
264129476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
264229476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
264329476558STakashi Iwai 	return 1;
264429476558STakashi Iwai }
264529476558STakashi Iwai 
264629476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
264729476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
264829476558STakashi Iwai 	.info = in_jack_mode_info,
264929476558STakashi Iwai 	.get = in_jack_mode_get,
265029476558STakashi Iwai 	.put = in_jack_mode_put,
265129476558STakashi Iwai };
265229476558STakashi Iwai 
26535f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
26545f171baaSTakashi Iwai {
26555f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
26565f171baaSTakashi Iwai 	int nitems = 0;
2657f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
26585f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
26595f171baaSTakashi Iwai 	return nitems ? nitems : 1;
26605f171baaSTakashi Iwai }
26615f171baaSTakashi Iwai 
266229476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
266329476558STakashi Iwai {
266429476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
266529476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2666975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
26675f171baaSTakashi Iwai 	unsigned int defcfg;
26685f171baaSTakashi Iwai 
2669f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2670f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
267129476558STakashi Iwai 
267229476558STakashi Iwai 	/* no jack mode for fixed pins */
267329476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
267429476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
267529476558STakashi Iwai 		return 0;
267629476558STakashi Iwai 
267729476558STakashi Iwai 	/* no multiple vref caps? */
26785f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
267929476558STakashi Iwai 		return 0;
268029476558STakashi Iwai 
268129476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
268229476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
268329476558STakashi Iwai 	if (!knew)
268429476558STakashi Iwai 		return -ENOMEM;
268529476558STakashi Iwai 	knew->private_value = pin;
268629476558STakashi Iwai 	return 0;
268729476558STakashi Iwai }
268829476558STakashi Iwai 
26895f171baaSTakashi Iwai /*
26905f171baaSTakashi Iwai  * HP/mic shared jack mode
26915f171baaSTakashi Iwai  */
26925f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
26935f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
26945f171baaSTakashi Iwai {
26955f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
26965f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
26975f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
26985f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
26995f171baaSTakashi Iwai 	const char *text = NULL;
27005f171baaSTakashi Iwai 	int idx;
27015f171baaSTakashi Iwai 
27025f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
27035f171baaSTakashi Iwai 	uinfo->count = 1;
27045f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
27055f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
27065f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
27075f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
27085f171baaSTakashi Iwai 	if (idx < out_jacks) {
27095f171baaSTakashi Iwai 		if (out_jacks > 1)
27105f171baaSTakashi Iwai 			text = out_jack_texts[idx];
27115f171baaSTakashi Iwai 		else
27125f171baaSTakashi Iwai 			text = "Headphone Out";
27135f171baaSTakashi Iwai 	} else {
27145f171baaSTakashi Iwai 		idx -= out_jacks;
27155f171baaSTakashi Iwai 		if (in_jacks > 1) {
27165f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27175f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
27185f171baaSTakashi Iwai 		} else
27195f171baaSTakashi Iwai 			text = "Mic In";
27205f171baaSTakashi Iwai 	}
27215f171baaSTakashi Iwai 
27225f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
27235f171baaSTakashi Iwai 	return 0;
27245f171baaSTakashi Iwai }
27255f171baaSTakashi Iwai 
27265f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
27275f171baaSTakashi Iwai {
27285f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27295f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27305f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
27315f171baaSTakashi Iwai 	int idx = 0;
27325f171baaSTakashi Iwai 
27335f171baaSTakashi Iwai 	if (val & PIN_OUT) {
27345f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
27355f171baaSTakashi Iwai 			idx = 1;
27365f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
27375f171baaSTakashi Iwai 		idx = out_jacks;
27385f171baaSTakashi Iwai 		if (in_jacks > 1) {
27395f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27405f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
27415f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
27425f171baaSTakashi Iwai 		}
27435f171baaSTakashi Iwai 	}
27445f171baaSTakashi Iwai 	return idx;
27455f171baaSTakashi Iwai }
27465f171baaSTakashi Iwai 
27475f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
27485f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27495f171baaSTakashi Iwai {
27505f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27515f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27525f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
27535f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
27545f171baaSTakashi Iwai 	return 0;
27555f171baaSTakashi Iwai }
27565f171baaSTakashi Iwai 
27575f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
27585f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
27595f171baaSTakashi Iwai {
27605f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
27615f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
27625f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
27635f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
27645f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
27655f171baaSTakashi Iwai 
27665f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
27675f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
27685f171baaSTakashi Iwai 	if (oldval == idx)
27695f171baaSTakashi Iwai 		return 0;
27705f171baaSTakashi Iwai 
27715f171baaSTakashi Iwai 	if (idx < out_jacks) {
27725f171baaSTakashi Iwai 		if (out_jacks > 1)
27735f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
27745f171baaSTakashi Iwai 		else
27755f171baaSTakashi Iwai 			val = PIN_HP;
27765f171baaSTakashi Iwai 	} else {
27775f171baaSTakashi Iwai 		idx -= out_jacks;
27785f171baaSTakashi Iwai 		if (in_jacks > 1) {
27795f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
27805f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
27813f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
27823f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
27835f171baaSTakashi Iwai 		} else
278416c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
27855f171baaSTakashi Iwai 	}
27865f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2787963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
27888ba955ceSTakashi Iwai 
27895f171baaSTakashi Iwai 	return 1;
27905f171baaSTakashi Iwai }
27915f171baaSTakashi Iwai 
27925f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
27935f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
27945f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
27955f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
27965f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
27975f171baaSTakashi Iwai };
27985f171baaSTakashi Iwai 
27995f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
28005f171baaSTakashi Iwai {
28015f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28025f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
28035f171baaSTakashi Iwai 
28045f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
28055f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
28065f171baaSTakashi Iwai 	if (!knew)
28075f171baaSTakashi Iwai 		return -ENOMEM;
28085f171baaSTakashi Iwai 	knew->private_value = pin;
28098ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
28105f171baaSTakashi Iwai 	return 0;
28115f171baaSTakashi Iwai }
2812352f7f91STakashi Iwai 
2813352f7f91STakashi Iwai /*
2814352f7f91STakashi Iwai  * Parse input paths
2815352f7f91STakashi Iwai  */
2816352f7f91STakashi Iwai 
2817352f7f91STakashi Iwai /* add the powersave loopback-list entry */
28180186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2819352f7f91STakashi Iwai {
2820352f7f91STakashi Iwai 	struct hda_amp_list *list;
2821352f7f91STakashi Iwai 
28220186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
28230186f4f4STakashi Iwai 	if (!list)
28240186f4f4STakashi Iwai 		return -ENOMEM;
2825352f7f91STakashi Iwai 	list->nid = mix;
2826352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2827352f7f91STakashi Iwai 	list->idx = idx;
28280186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
28290186f4f4STakashi Iwai 	return 0;
2830cb53c626STakashi Iwai }
2831cb53c626STakashi Iwai 
28322ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
28332ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
28342ded3e5bSTakashi Iwai  */
28352ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
28362ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
28372ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
28382ded3e5bSTakashi Iwai {
28392ded3e5bSTakashi Iwai 	int idx, num_conns;
28402ded3e5bSTakashi Iwai 	const hda_nid_t *list;
28412ded3e5bSTakashi Iwai 	hda_nid_t nid;
28422ded3e5bSTakashi Iwai 
28432ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
28442ded3e5bSTakashi Iwai 	if (idx < 0)
28452ded3e5bSTakashi Iwai 		return false;
28462ded3e5bSTakashi Iwai 
28472ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
28482ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
28492ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28502ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
28512ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
28522ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
28532ded3e5bSTakashi Iwai 		return true;
28542ded3e5bSTakashi Iwai 
28552ded3e5bSTakashi Iwai 	/* check leaf node */
28562ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
28572ded3e5bSTakashi Iwai 	if (num_conns < idx)
28582ded3e5bSTakashi Iwai 		return false;
28592ded3e5bSTakashi Iwai 	nid = list[idx];
28602ded3e5bSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT))
28612ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
28622ded3e5bSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT))
28632ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
28642ded3e5bSTakashi Iwai 
28652ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
28662ded3e5bSTakashi Iwai }
28672ded3e5bSTakashi Iwai 
2868352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2869196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2870196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2871352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
28721da177e4SLinus Torvalds {
2873352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2874352f7f91STakashi Iwai 	struct nid_path *path;
28752ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
2876352f7f91STakashi Iwai 	int err, idx;
28771da177e4SLinus Torvalds 
28782ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
28792ded3e5bSTakashi Iwai 		return 0;
2880352f7f91STakashi Iwai 
28813ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2882352f7f91STakashi Iwai 	if (!path)
2883352f7f91STakashi Iwai 		return -EINVAL;
28840c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2885196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2886352f7f91STakashi Iwai 
2887352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
28882ded3e5bSTakashi Iwai 	if (mix_val) {
28892ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
2890d13bd412STakashi Iwai 		if (err < 0)
28911da177e4SLinus Torvalds 			return err;
28922ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
28931da177e4SLinus Torvalds 	}
28941da177e4SLinus Torvalds 
28952ded3e5bSTakashi Iwai 	if (mute_val) {
28962ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
2897d13bd412STakashi Iwai 		if (err < 0)
28981da177e4SLinus Torvalds 			return err;
28992ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
29001da177e4SLinus Torvalds 	}
29011da177e4SLinus Torvalds 
2902352f7f91STakashi Iwai 	path->active = true;
29030186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
29040186f4f4STakashi Iwai 	if (err < 0)
29050186f4f4STakashi Iwai 		return err;
2906e4a395e7STakashi Iwai 
2907e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
2908e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
2909e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
2910e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
2911e4a395e7STakashi Iwai 		if (path) {
2912e4a395e7STakashi Iwai 			print_nid_path("loopback-merge", path);
2913e4a395e7STakashi Iwai 			path->active = true;
2914e4a395e7STakashi Iwai 			spec->loopback_merge_path =
2915e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
2916e4a395e7STakashi Iwai 		}
2917e4a395e7STakashi Iwai 	}
2918e4a395e7STakashi Iwai 
2919352f7f91STakashi Iwai 	return 0;
29201da177e4SLinus Torvalds }
29211da177e4SLinus Torvalds 
2922352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
29231da177e4SLinus Torvalds {
2924352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2925352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2926352f7f91STakashi Iwai }
2927352f7f91STakashi Iwai 
2928352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2929352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2930352f7f91STakashi Iwai {
2931352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2932352f7f91STakashi Iwai 	hda_nid_t nid;
2933352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2934352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2935352f7f91STakashi Iwai 	int i, nums = 0;
2936352f7f91STakashi Iwai 
2937352f7f91STakashi Iwai 	nid = codec->start_nid;
2938352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2939352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2940352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2941352f7f91STakashi Iwai 
2942352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2943352f7f91STakashi Iwai 			continue;
2944352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2945352f7f91STakashi Iwai 		if (++nums >= max_nums)
2946352f7f91STakashi Iwai 			break;
2947352f7f91STakashi Iwai 	}
2948352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
29490ffd534eSTakashi Iwai 
29500ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
29510ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
29520ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
29530ffd534eSTakashi Iwai 
2954352f7f91STakashi Iwai 	return nums;
2955352f7f91STakashi Iwai }
2956352f7f91STakashi Iwai 
2957352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2958352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2959352f7f91STakashi Iwai  */
2960352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2961352f7f91STakashi Iwai {
2962352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2963352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
29643a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2965352f7f91STakashi Iwai 	int i, n, nums;
2966352f7f91STakashi Iwai 
2967352f7f91STakashi Iwai 	nums = 0;
29683a65bcdcSTakashi Iwai 	ok_bits = 0;
2969352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2970352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
29713a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2972352f7f91STakashi Iwai 				break;
2973352f7f91STakashi Iwai 		}
29743a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
29753a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
29763a65bcdcSTakashi Iwai 			nums++;
29773a65bcdcSTakashi Iwai 		}
2978352f7f91STakashi Iwai 	}
2979352f7f91STakashi Iwai 
29803a65bcdcSTakashi Iwai 	if (!ok_bits) {
2981352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2982352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2983352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
29843a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2985352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2986352f7f91STakashi Iwai 					break;
2987352f7f91STakashi Iwai 				}
2988352f7f91STakashi Iwai 			}
2989352f7f91STakashi Iwai 		}
2990352f7f91STakashi Iwai 
2991352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2992352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2993352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
29943a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
29953a65bcdcSTakashi Iwai 		nums = 0;
29963a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
29973a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
29983a65bcdcSTakashi Iwai 				continue;
29993a65bcdcSTakashi Iwai 			if (n != nums) {
30003a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3001980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3002980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3003980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
30043a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
30053a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
30063a65bcdcSTakashi Iwai 				}
3007980428ceSTakashi Iwai 			}
30083a65bcdcSTakashi Iwai 			nums++;
30093a65bcdcSTakashi Iwai 		}
3010352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3011352f7f91STakashi Iwai 	}
3012352f7f91STakashi Iwai 
3013967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3014967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
3015352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
3016352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3017352f7f91STakashi Iwai 	}
3018352f7f91STakashi Iwai 
3019352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3020352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3021352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3022352f7f91STakashi Iwai 
30231da177e4SLinus Torvalds 	return 0;
30241da177e4SLinus Torvalds }
30251da177e4SLinus Torvalds 
3026f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3027f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
30289dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
30299dba205bSTakashi Iwai 				const char *label, int anchor)
3030f3fc0b0bSTakashi Iwai {
3031f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3032f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3033f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3034f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3035f3fc0b0bSTakashi Iwai 	int c;
3036f3fc0b0bSTakashi Iwai 
3037f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3038f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3039f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3040f3fc0b0bSTakashi Iwai 
3041f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3042f3fc0b0bSTakashi Iwai 			continue;
3043f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3044f3fc0b0bSTakashi Iwai 		if (!path)
3045f3fc0b0bSTakashi Iwai 			continue;
3046f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
3047f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3048f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3049f3fc0b0bSTakashi Iwai 
3050f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3051967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3052967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3053f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
30549dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
3055f3fc0b0bSTakashi Iwai 			imux_added = true;
3056f3fc0b0bSTakashi Iwai 		}
3057f3fc0b0bSTakashi Iwai 	}
3058f3fc0b0bSTakashi Iwai 
3059f3fc0b0bSTakashi Iwai 	return 0;
3060f3fc0b0bSTakashi Iwai }
3061f3fc0b0bSTakashi Iwai 
30621da177e4SLinus Torvalds /*
3063352f7f91STakashi Iwai  * create playback/capture controls for input pins
30641da177e4SLinus Torvalds  */
30659dba205bSTakashi Iwai 
3066c970042cSTakashi Iwai /* fill the label for each input at first */
3067c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3068c970042cSTakashi Iwai {
3069c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3070c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3071c970042cSTakashi Iwai 	int i;
3072c970042cSTakashi Iwai 
3073c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3074c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3075c970042cSTakashi Iwai 		const char *label;
3076c970042cSTakashi Iwai 		int j, idx;
3077c970042cSTakashi Iwai 
3078c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3079c970042cSTakashi Iwai 			continue;
3080c970042cSTakashi Iwai 
3081c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3082c970042cSTakashi Iwai 		idx = 0;
30838e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3084c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3085c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3086c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3087c970042cSTakashi Iwai 				break;
3088c970042cSTakashi Iwai 			}
3089c970042cSTakashi Iwai 		}
3090c970042cSTakashi Iwai 
3091c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3092c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3093c970042cSTakashi Iwai 	}
3094c970042cSTakashi Iwai 
3095c970042cSTakashi Iwai 	return 0;
3096c970042cSTakashi Iwai }
3097c970042cSTakashi Iwai 
30989dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
30999dba205bSTakashi Iwai 
3100352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3101a7da6ce5STakashi Iwai {
3102352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3103352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3104352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3105352f7f91STakashi Iwai 	int num_adcs;
3106c970042cSTakashi Iwai 	int i, err;
31072c12c30dSTakashi Iwai 	unsigned int val;
3108a7da6ce5STakashi Iwai 
3109352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3110352f7f91STakashi Iwai 	if (num_adcs < 0)
3111352f7f91STakashi Iwai 		return 0;
3112352f7f91STakashi Iwai 
3113c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3114c970042cSTakashi Iwai 	if (err < 0)
3115c970042cSTakashi Iwai 		return err;
3116c970042cSTakashi Iwai 
3117352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3118352f7f91STakashi Iwai 		hda_nid_t pin;
3119352f7f91STakashi Iwai 
3120352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3121352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3122352f7f91STakashi Iwai 			continue;
3123352f7f91STakashi Iwai 
31242c12c30dSTakashi Iwai 		val = PIN_IN;
31252c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
31262c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
312793c9d8aeSTakashi Iwai 		if (pin != spec->hp_mic_pin)
31282c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
31292c12c30dSTakashi Iwai 
3130352f7f91STakashi Iwai 		if (mixer) {
3131352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3132196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3133c970042cSTakashi Iwai 						       spec->input_labels[i],
3134c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3135c970042cSTakashi Iwai 						       mixer);
3136a7da6ce5STakashi Iwai 				if (err < 0)
3137a7da6ce5STakashi Iwai 					return err;
3138a7da6ce5STakashi Iwai 			}
3139352f7f91STakashi Iwai 		}
3140352f7f91STakashi Iwai 
3141c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3142c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3143f3fc0b0bSTakashi Iwai 		if (err < 0)
3144f3fc0b0bSTakashi Iwai 			return err;
314529476558STakashi Iwai 
3146f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
314729476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
314829476558STakashi Iwai 			if (err < 0)
314929476558STakashi Iwai 				return err;
315029476558STakashi Iwai 		}
3151352f7f91STakashi Iwai 	}
3152f3fc0b0bSTakashi Iwai 
3153f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
31549dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3155f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3156f3fc0b0bSTakashi Iwai 		if (err < 0)
3157f3fc0b0bSTakashi Iwai 			return err;
3158352f7f91STakashi Iwai 	}
3159352f7f91STakashi Iwai 
3160a7da6ce5STakashi Iwai 	return 0;
3161a7da6ce5STakashi Iwai }
3162a7da6ce5STakashi Iwai 
31631da177e4SLinus Torvalds 
3164352f7f91STakashi Iwai /*
3165352f7f91STakashi Iwai  * input source mux
3166352f7f91STakashi Iwai  */
3167352f7f91STakashi Iwai 
3168c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3169c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3170352f7f91STakashi Iwai {
3171352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3172b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3173b56fa1edSDavid Henningsson 		snd_BUG();
3174b56fa1edSDavid Henningsson 		return NULL;
3175b56fa1edSDavid Henningsson 	}
3176352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3177352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3178d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3179b56fa1edSDavid Henningsson 		snd_BUG();
3180b56fa1edSDavid Henningsson 		return NULL;
3181b56fa1edSDavid Henningsson 	}
3182c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
318397ec558aSTakashi Iwai }
3184352f7f91STakashi Iwai 
3185352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3186352f7f91STakashi Iwai 		      unsigned int idx);
3187352f7f91STakashi Iwai 
3188352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3189352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3190352f7f91STakashi Iwai {
3191352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3192352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3193352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3194352f7f91STakashi Iwai }
3195352f7f91STakashi Iwai 
3196352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3197352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3198352f7f91STakashi Iwai {
3199352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3200352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
32012a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
32022a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3203352f7f91STakashi Iwai 
3204352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
32051da177e4SLinus Torvalds 	return 0;
32061da177e4SLinus Torvalds }
32071da177e4SLinus Torvalds 
3208352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3209352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
32101da177e4SLinus Torvalds {
3211352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
32122a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3213352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3214352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3215352f7f91STakashi Iwai }
3216352f7f91STakashi Iwai 
3217352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
32181da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3219352f7f91STakashi Iwai 	.name = "Input Source",
3220352f7f91STakashi Iwai 	.info = mux_enum_info,
3221352f7f91STakashi Iwai 	.get = mux_enum_get,
3222352f7f91STakashi Iwai 	.put = mux_enum_put,
32231da177e4SLinus Torvalds };
3224071c73adSTakashi Iwai 
322547d46abbSTakashi Iwai /*
322647d46abbSTakashi Iwai  * capture volume and capture switch ctls
322747d46abbSTakashi Iwai  */
322847d46abbSTakashi Iwai 
3229352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3230352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3231071c73adSTakashi Iwai 
323247d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3233352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3234352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3235352f7f91STakashi Iwai 			  put_call_t func, int type)
3236352f7f91STakashi Iwai {
3237352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3238352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3239352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3240352f7f91STakashi Iwai 	struct nid_path *path;
3241352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3242071c73adSTakashi Iwai 
3243352f7f91STakashi Iwai 	imux = &spec->input_mux;
3244a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3245352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
324647d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
324747d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
324847d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
324947d46abbSTakashi Iwai 	 */
3250352f7f91STakashi Iwai 	codec->cached_write = 1;
3251352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3252c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3253c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3254352f7f91STakashi Iwai 			continue;
3255352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3256352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3257352f7f91STakashi Iwai 		if (err < 0)
3258352f7f91STakashi Iwai 			goto error;
3259352f7f91STakashi Iwai 	}
3260352f7f91STakashi Iwai  error:
3261352f7f91STakashi Iwai 	codec->cached_write = 0;
3262352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3263dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec); /* flush the updates */
3264352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
3265a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3266352f7f91STakashi Iwai 	return err;
3267352f7f91STakashi Iwai }
3268352f7f91STakashi Iwai 
3269352f7f91STakashi Iwai /* capture volume ctl callbacks */
3270352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3271352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3272352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3273352f7f91STakashi Iwai 
3274352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3275352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3276352f7f91STakashi Iwai {
3277352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3278352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3279352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3280352f7f91STakashi Iwai }
3281352f7f91STakashi Iwai 
3282352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3283352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3284352f7f91STakashi Iwai 	.name = "Capture Volume",
3285352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3286352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3287352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3288352f7f91STakashi Iwai 	.info = cap_vol_info,
3289352f7f91STakashi Iwai 	.get = cap_vol_get,
3290352f7f91STakashi Iwai 	.put = cap_vol_put,
3291352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3292352f7f91STakashi Iwai };
3293352f7f91STakashi Iwai 
3294352f7f91STakashi Iwai /* capture switch ctl callbacks */
3295352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3296352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3297352f7f91STakashi Iwai 
3298352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3299352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3300352f7f91STakashi Iwai {
3301a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3302352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3303352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3304352f7f91STakashi Iwai }
3305352f7f91STakashi Iwai 
3306352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3307352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3308352f7f91STakashi Iwai 	.name = "Capture Switch",
3309352f7f91STakashi Iwai 	.info = cap_sw_info,
3310352f7f91STakashi Iwai 	.get = cap_sw_get,
3311352f7f91STakashi Iwai 	.put = cap_sw_put,
3312352f7f91STakashi Iwai };
3313352f7f91STakashi Iwai 
3314352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3315352f7f91STakashi Iwai {
3316352f7f91STakashi Iwai 	hda_nid_t nid;
3317352f7f91STakashi Iwai 	int i, depth;
3318352f7f91STakashi Iwai 
3319352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3320352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3321352f7f91STakashi Iwai 		if (depth >= path->depth)
3322352f7f91STakashi Iwai 			return -EINVAL;
3323352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3324352f7f91STakashi Iwai 		nid = path->path[i];
3325352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3326352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3327352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3328352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3329352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3330352f7f91STakashi Iwai 				int idx = path->idx[i];
3331352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3332352f7f91STakashi Iwai 					idx = 0;
3333352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3334352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3335352f7f91STakashi Iwai 			}
3336352f7f91STakashi Iwai 		}
3337352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3338352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3339352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3340352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3341352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3342352f7f91STakashi Iwai 				int idx = path->idx[i];
3343352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3344352f7f91STakashi Iwai 					idx = 0;
3345352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3346352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3347352f7f91STakashi Iwai 			}
3348352f7f91STakashi Iwai 		}
3349352f7f91STakashi Iwai 	}
3350352f7f91STakashi Iwai 	return 0;
3351352f7f91STakashi Iwai }
3352352f7f91STakashi Iwai 
3353352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3354352f7f91STakashi Iwai {
3355352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3356352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3357352f7f91STakashi Iwai 	unsigned int val;
3358352f7f91STakashi Iwai 	int i;
3359352f7f91STakashi Iwai 
3360352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3361352f7f91STakashi Iwai 		return false;
3362352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3363352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3364352f7f91STakashi Iwai 			continue;
3365352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3366352f7f91STakashi Iwai 			return false;
3367352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3368352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3369352f7f91STakashi Iwai 	}
3370352f7f91STakashi Iwai 	return false;
3371352f7f91STakashi Iwai }
3372352f7f91STakashi Iwai 
3373a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3374a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3375a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3376a35bd1e3STakashi Iwai {
3377a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3378a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3379a35bd1e3STakashi Iwai 	int ret;
3380a35bd1e3STakashi Iwai 
3381a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3382a35bd1e3STakashi Iwai 	if (ret < 0)
3383a35bd1e3STakashi Iwai 		return ret;
3384a35bd1e3STakashi Iwai 
3385a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
3386a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
3387a35bd1e3STakashi Iwai 
3388a35bd1e3STakashi Iwai 	return ret;
3389a35bd1e3STakashi Iwai }
3390a35bd1e3STakashi Iwai 
3391352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3392352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3393352f7f91STakashi Iwai 			      bool inv_dmic)
3394352f7f91STakashi Iwai {
3395352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3396975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3397352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3398352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3399352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3400a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3401352f7f91STakashi Iwai 
3402352f7f91STakashi Iwai 	if (!ctl)
3403352f7f91STakashi Iwai 		return 0;
3404352f7f91STakashi Iwai 
3405352f7f91STakashi Iwai 	if (label)
3406352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3407352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3408352f7f91STakashi Iwai 	else
3409352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3410352f7f91STakashi Iwai 			 "Capture %s", sfx);
3411a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3412352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3413a35bd1e3STakashi Iwai 	if (!knew)
3414a35bd1e3STakashi Iwai 		return -ENOMEM;
3415a90229e0STakashi Iwai 	if (is_switch)
3416a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3417a35bd1e3STakashi Iwai 	if (!inv_dmic)
3418a35bd1e3STakashi Iwai 		return 0;
3419352f7f91STakashi Iwai 
3420352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3421352f7f91STakashi Iwai 	if (label)
3422352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3423352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3424352f7f91STakashi Iwai 	else
3425352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3426352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3427a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3428352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3429a35bd1e3STakashi Iwai 	if (!knew)
3430a35bd1e3STakashi Iwai 		return -ENOMEM;
3431a90229e0STakashi Iwai 	if (is_switch)
3432a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3433a35bd1e3STakashi Iwai 	return 0;
3434352f7f91STakashi Iwai }
3435352f7f91STakashi Iwai 
3436352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3437352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3438352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3439352f7f91STakashi Iwai 				     bool inv_dmic)
3440352f7f91STakashi Iwai {
3441352f7f91STakashi Iwai 	int err;
3442352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3443352f7f91STakashi Iwai 	if (err < 0)
3444352f7f91STakashi Iwai 		return err;
3445352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3446071c73adSTakashi Iwai 	if (err < 0)
3447071c73adSTakashi Iwai 		return err;
3448071c73adSTakashi Iwai 	return 0;
34491da177e4SLinus Torvalds }
3450071c73adSTakashi Iwai 
3451352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3452352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3453352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3454352f7f91STakashi Iwai {
3455352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3456352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3457352f7f91STakashi Iwai 
3458352f7f91STakashi Iwai 	if (vol_ctl) {
345912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3460352f7f91STakashi Iwai 		if (!knew)
3461352f7f91STakashi Iwai 			return -ENOMEM;
3462352f7f91STakashi Iwai 		knew->index = idx;
3463352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3464352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3465352f7f91STakashi Iwai 	}
3466352f7f91STakashi Iwai 	if (sw_ctl) {
346712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3468352f7f91STakashi Iwai 		if (!knew)
3469352f7f91STakashi Iwai 			return -ENOMEM;
3470352f7f91STakashi Iwai 		knew->index = idx;
3471352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3472352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3473352f7f91STakashi Iwai 	}
3474352f7f91STakashi Iwai 	return 0;
3475352f7f91STakashi Iwai }
3476352f7f91STakashi Iwai 
3477352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3478352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3479352f7f91STakashi Iwai {
3480352f7f91STakashi Iwai 	struct nid_path *path;
3481352f7f91STakashi Iwai 	unsigned int ctl;
3482352f7f91STakashi Iwai 	int i;
3483352f7f91STakashi Iwai 
3484c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3485352f7f91STakashi Iwai 	if (!path)
3486352f7f91STakashi Iwai 		return 0;
3487352f7f91STakashi Iwai 	ctl = path->ctls[type];
3488352f7f91STakashi Iwai 	if (!ctl)
3489352f7f91STakashi Iwai 		return 0;
3490352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3491c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3492352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3493352f7f91STakashi Iwai 			return 0;
3494352f7f91STakashi Iwai 	}
3495352f7f91STakashi Iwai 	return ctl;
3496352f7f91STakashi Iwai }
3497352f7f91STakashi Iwai 
3498352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3499352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3500352f7f91STakashi Iwai {
3501352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3502352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3503c970042cSTakashi Iwai 	int i, err, type;
3504352f7f91STakashi Iwai 
3505352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3506352f7f91STakashi Iwai 		bool inv_dmic;
3507c970042cSTakashi Iwai 		int idx;
35089dba205bSTakashi Iwai 
3509c970042cSTakashi Iwai 		idx = imux->items[i].index;
3510c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
35119dba205bSTakashi Iwai 			continue;
3512352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3513352f7f91STakashi Iwai 
3514352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3515c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3516c970042cSTakashi Iwai 						 spec->input_labels[idx],
3517c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3518c970042cSTakashi Iwai 						 type,
3519352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3520352f7f91STakashi Iwai 						 inv_dmic);
3521d13bd412STakashi Iwai 			if (err < 0)
3522071c73adSTakashi Iwai 				return err;
3523352f7f91STakashi Iwai 		}
3524352f7f91STakashi Iwai 	}
3525071c73adSTakashi Iwai 	return 0;
3526352f7f91STakashi Iwai }
3527071c73adSTakashi Iwai 
3528352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3529352f7f91STakashi Iwai {
3530352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3531352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3532352f7f91STakashi Iwai 	int i, n, nums, err;
3533352f7f91STakashi Iwai 
3534352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3535352f7f91STakashi Iwai 		nums = 1;
3536352f7f91STakashi Iwai 	else
3537352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3538352f7f91STakashi Iwai 
3539352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3540352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3541624d914dSTakashi Iwai 		const char *name;
3542624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3543624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3544352f7f91STakashi Iwai 		if (!knew)
3545352f7f91STakashi Iwai 			return -ENOMEM;
3546352f7f91STakashi Iwai 		knew->count = nums;
3547352f7f91STakashi Iwai 	}
3548352f7f91STakashi Iwai 
3549352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3550352f7f91STakashi Iwai 		bool multi = false;
355199a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3552352f7f91STakashi Iwai 		bool inv_dmic = false;
3553352f7f91STakashi Iwai 		int vol, sw;
3554352f7f91STakashi Iwai 
3555352f7f91STakashi Iwai 		vol = sw = 0;
3556352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3557352f7f91STakashi Iwai 			struct nid_path *path;
3558c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3559352f7f91STakashi Iwai 			if (!path)
3560352f7f91STakashi Iwai 				continue;
3561352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3562352f7f91STakashi Iwai 			if (!vol)
3563352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
356499a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3565352f7f91STakashi Iwai 				multi = true;
356699a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
356799a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
356899a5592dSDavid Henningsson 					multi_cap_vol = true;
356999a5592dSDavid Henningsson 			}
3570352f7f91STakashi Iwai 			if (!sw)
3571352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
357299a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3573352f7f91STakashi Iwai 				multi = true;
357499a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
357599a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
357699a5592dSDavid Henningsson 					multi_cap_vol = true;
357799a5592dSDavid Henningsson 			}
3578352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3579352f7f91STakashi Iwai 				inv_dmic = true;
3580352f7f91STakashi Iwai 		}
3581352f7f91STakashi Iwai 
3582352f7f91STakashi Iwai 		if (!multi)
3583352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3584352f7f91STakashi Iwai 							inv_dmic);
3585ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3586352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3587352f7f91STakashi Iwai 		else
3588352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3589d13bd412STakashi Iwai 		if (err < 0)
3590071c73adSTakashi Iwai 			return err;
3591071c73adSTakashi Iwai 	}
3592071c73adSTakashi Iwai 
35931da177e4SLinus Torvalds 	return 0;
35941da177e4SLinus Torvalds }
35951da177e4SLinus Torvalds 
3596352f7f91STakashi Iwai /*
3597352f7f91STakashi Iwai  * add mic boosts if needed
3598352f7f91STakashi Iwai  */
35996f7c83afSTakashi Iwai 
36006f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
36016f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
36026f7c83afSTakashi Iwai 			    int dir, int idx)
36036f7c83afSTakashi Iwai {
36046f7c83afSTakashi Iwai 	unsigned int step;
36056f7c83afSTakashi Iwai 
36066f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
36076f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
36086f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
36096f7c83afSTakashi Iwai 		return false;
36106f7c83afSTakashi Iwai 
36116f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
36126f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
36136f7c83afSTakashi Iwai 	if (step < 0x20)
36146f7c83afSTakashi Iwai 		return false;
36156f7c83afSTakashi Iwai 	return true;
36166f7c83afSTakashi Iwai }
36176f7c83afSTakashi Iwai 
36186f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
36196f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
36206f7c83afSTakashi Iwai 				       struct nid_path *path)
36216f7c83afSTakashi Iwai {
36226f7c83afSTakashi Iwai 	unsigned int val = 0;
36236f7c83afSTakashi Iwai 	hda_nid_t nid;
36246f7c83afSTakashi Iwai 	int depth;
36256f7c83afSTakashi Iwai 
36266f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
36276f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
36286f7c83afSTakashi Iwai 			break;
36296f7c83afSTakashi Iwai 		nid = path->path[depth];
36306f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
36316f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
36326f7c83afSTakashi Iwai 			break;
36336f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
36346f7c83afSTakashi Iwai 					   path->idx[depth])) {
36356f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
36366f7c83afSTakashi Iwai 						  HDA_INPUT);
36376f7c83afSTakashi Iwai 			break;
36386f7c83afSTakashi Iwai 		}
36396f7c83afSTakashi Iwai 	}
36406f7c83afSTakashi Iwai 
36416f7c83afSTakashi Iwai 	return val;
36426f7c83afSTakashi Iwai }
36436f7c83afSTakashi Iwai 
3644352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3645352f7f91STakashi Iwai {
3646352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3647352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
36486f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3649a35bd1e3STakashi Iwai 	int i;
3650352f7f91STakashi Iwai 
36516f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
36526f7c83afSTakashi Iwai 		return 0;
36536f7c83afSTakashi Iwai 
36546f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3655352f7f91STakashi Iwai 		struct nid_path *path;
3656352f7f91STakashi Iwai 		unsigned int val;
36576f7c83afSTakashi Iwai 		int idx;
3658975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3659352f7f91STakashi Iwai 
36606f7c83afSTakashi Iwai 		idx = imux->items[i].index;
36616f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
366202aba550SDavid Henningsson 			continue;
366302aba550SDavid Henningsson 
36646f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
36651799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
36666f7c83afSTakashi Iwai 			continue;
36676f7c83afSTakashi Iwai 
36686f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
36696f7c83afSTakashi Iwai 		if (!path)
36706f7c83afSTakashi Iwai 			continue;
36716f7c83afSTakashi Iwai 
36726f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
36736f7c83afSTakashi Iwai 		if (!val)
36746f7c83afSTakashi Iwai 			continue;
36756f7c83afSTakashi Iwai 
36766f7c83afSTakashi Iwai 		/* create a boost control */
3677352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
36786f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3679a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3680a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3681a35bd1e3STakashi Iwai 			return -ENOMEM;
3682352f7f91STakashi Iwai 
3683352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3684352f7f91STakashi Iwai 	}
3685352f7f91STakashi Iwai 	return 0;
3686352f7f91STakashi Iwai }
3687352f7f91STakashi Iwai 
3688352f7f91STakashi Iwai /*
3689352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3690352f7f91STakashi Iwai  */
3691352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3692352f7f91STakashi Iwai {
3693352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
36940c8c0f56STakashi Iwai 	struct nid_path *path;
3695352f7f91STakashi Iwai 	int i, nums;
36962c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3697352f7f91STakashi Iwai 
3698352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3699352f7f91STakashi Iwai 	nums = 0;
3700352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
37012c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3702352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3703352f7f91STakashi Iwai 		if (!dig_nid)
3704352f7f91STakashi Iwai 			continue;
37053ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
37060c8c0f56STakashi Iwai 		if (!path)
3707352f7f91STakashi Iwai 			continue;
37080c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3709e1284af7STakashi Iwai 		path->active = true;
3710196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
37112c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3712352f7f91STakashi Iwai 		if (!nums) {
3713352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3714352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3715352f7f91STakashi Iwai 		} else {
3716352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3717352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3718352f7f91STakashi Iwai 			break;
3719352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3720352f7f91STakashi Iwai 		}
3721352f7f91STakashi Iwai 		nums++;
3722352f7f91STakashi Iwai 	}
3723352f7f91STakashi Iwai 
3724352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
37252c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3726352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3727352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3728352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3729352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3730352f7f91STakashi Iwai 				continue;
3731352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3732352f7f91STakashi Iwai 				continue;
37332c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3734352f7f91STakashi Iwai 			if (path) {
37350c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3736352f7f91STakashi Iwai 				path->active = true;
3737352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
37382430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
37392c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3740352f7f91STakashi Iwai 				break;
3741352f7f91STakashi Iwai 			}
3742352f7f91STakashi Iwai 		}
3743352f7f91STakashi Iwai 	}
3744352f7f91STakashi Iwai }
3745352f7f91STakashi Iwai 
37461da177e4SLinus Torvalds 
37471da177e4SLinus Torvalds /*
3748352f7f91STakashi Iwai  * input MUX handling
37491da177e4SLinus Torvalds  */
37501da177e4SLinus Torvalds 
3751352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3752352f7f91STakashi Iwai 
3753352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3754352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3755352f7f91STakashi Iwai 		      unsigned int idx)
3756352f7f91STakashi Iwai {
3757352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3758352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
375955196fffSTakashi Iwai 	struct nid_path *old_path, *path;
3760352f7f91STakashi Iwai 
3761352f7f91STakashi Iwai 	imux = &spec->input_mux;
3762352f7f91STakashi Iwai 	if (!imux->num_items)
37631da177e4SLinus Torvalds 		return 0;
37641da177e4SLinus Torvalds 
3765352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3766352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3767352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3768352f7f91STakashi Iwai 		return 0;
3769352f7f91STakashi Iwai 
377055196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
377155196fffSTakashi Iwai 	if (!old_path)
3772352f7f91STakashi Iwai 		return 0;
377355196fffSTakashi Iwai 	if (old_path->active)
377455196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
3775352f7f91STakashi Iwai 
3776352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3777352f7f91STakashi Iwai 
3778967303daSTakashi Iwai 	if (spec->hp_mic)
3779967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
3780352f7f91STakashi Iwai 
3781352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3782352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3783352f7f91STakashi Iwai 
3784c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3785352f7f91STakashi Iwai 	if (!path)
3786352f7f91STakashi Iwai 		return 0;
3787352f7f91STakashi Iwai 	if (path->active)
3788352f7f91STakashi Iwai 		return 0;
3789352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3790352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3791a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
379255196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
37931da177e4SLinus Torvalds 	return 1;
37941da177e4SLinus Torvalds }
37951da177e4SLinus Torvalds 
37961da177e4SLinus Torvalds 
37971da177e4SLinus Torvalds /*
3798352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
37991da177e4SLinus Torvalds  */
3800352f7f91STakashi Iwai 
3801352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3802352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
38031da177e4SLinus Torvalds {
380460ea8ca2STakashi Iwai 	int i;
380560ea8ca2STakashi Iwai 	bool present = false;
38061da177e4SLinus Torvalds 
3807352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3808352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3809352f7f91STakashi Iwai 		if (!nid)
3810352f7f91STakashi Iwai 			break;
38110b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
38120b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
38130b4df931STakashi Iwai 			continue;
381460ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
381560ea8ca2STakashi Iwai 			present = true;
38161da177e4SLinus Torvalds 	}
3817352f7f91STakashi Iwai 	return present;
38181da177e4SLinus Torvalds }
38191da177e4SLinus Torvalds 
3820352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3821352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
3822e80c60f3STakashi Iwai 			int *paths, bool mute)
38231da177e4SLinus Torvalds {
3824352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3825352f7f91STakashi Iwai 	int i;
38261da177e4SLinus Torvalds 
3827352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3828352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3829967303daSTakashi Iwai 		unsigned int val, oldval;
3830352f7f91STakashi Iwai 		if (!nid)
3831352f7f91STakashi Iwai 			break;
38327eebffd3STakashi Iwai 
38337eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
3834e80c60f3STakashi Iwai 			struct nid_path *path;
3835e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
3836e80c60f3STakashi Iwai 
3837e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
3838e80c60f3STakashi Iwai 			if (!path)
3839e80c60f3STakashi Iwai 				continue;
3840e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
3841e80c60f3STakashi Iwai 			if (!mute_nid)
3842e80c60f3STakashi Iwai 				continue;
38437eebffd3STakashi Iwai 			if (mute)
3844e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
38457eebffd3STakashi Iwai 			else
3846e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
38477eebffd3STakashi Iwai 			set_pin_eapd(codec, nid, !mute);
38487eebffd3STakashi Iwai 			continue;
38497eebffd3STakashi Iwai 		}
38507eebffd3STakashi Iwai 
3851967303daSTakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
3852967303daSTakashi Iwai 		if (oldval & PIN_IN)
3853967303daSTakashi Iwai 			continue; /* no mute for inputs */
3854352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3855352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3856352f7f91STakashi Iwai 		 */
38572c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
3858967303daSTakashi Iwai 			val = oldval & ~PIN_HP;
38592c12c30dSTakashi Iwai 		else
3860352f7f91STakashi Iwai 			val = 0;
38612c12c30dSTakashi Iwai 		if (!mute)
3862967303daSTakashi Iwai 			val |= oldval;
38632c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
38642c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
38652c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
38662c12c30dSTakashi Iwai 		 * init / resume again
38672c12c30dSTakashi Iwai 		 */
38682c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3869d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3870352f7f91STakashi Iwai 	}
3871352f7f91STakashi Iwai }
38721da177e4SLinus Torvalds 
3873352f7f91STakashi Iwai /* Toggle outputs muting */
38745d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3875352f7f91STakashi Iwai {
3876352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3877e80c60f3STakashi Iwai 	int *paths;
3878352f7f91STakashi Iwai 	int on;
3879352f7f91STakashi Iwai 
3880352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3881352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3882352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3883352f7f91STakashi Iwai 	 */
3884e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3885e80c60f3STakashi Iwai 		paths = spec->out_paths;
3886e80c60f3STakashi Iwai 	else
3887e80c60f3STakashi Iwai 		paths = spec->hp_paths;
3888352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3889e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
3890352f7f91STakashi Iwai 
3891352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3892352f7f91STakashi Iwai 		on = 0;
3893352f7f91STakashi Iwai 	else
3894352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3895352f7f91STakashi Iwai 	on |= spec->master_mute;
389647b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3897e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3898e80c60f3STakashi Iwai 		paths = spec->out_paths;
3899e80c60f3STakashi Iwai 	else
3900e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
3901352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
3902e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
3903352f7f91STakashi Iwai 
3904352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3905352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3906352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3907352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3908352f7f91STakashi Iwai 		return;
3909352f7f91STakashi Iwai 	if (!spec->automute_lo)
3910352f7f91STakashi Iwai 		on = 0;
3911352f7f91STakashi Iwai 	else
3912352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3913352f7f91STakashi Iwai 	on |= spec->master_mute;
391447b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3915e80c60f3STakashi Iwai 	paths = spec->out_paths;
3916352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3917e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
3918352f7f91STakashi Iwai }
39195d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3920352f7f91STakashi Iwai 
3921352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3922352f7f91STakashi Iwai {
3923352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3924352f7f91STakashi Iwai 	if (spec->automute_hook)
3925352f7f91STakashi Iwai 		spec->automute_hook(codec);
3926352f7f91STakashi Iwai 	else
39275d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
39287eebffd3STakashi Iwai 
39297eebffd3STakashi Iwai 	/* sync the whole vmaster slaves to reflect the new auto-mute status */
39307eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
39317eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
3932352f7f91STakashi Iwai }
3933352f7f91STakashi Iwai 
3934352f7f91STakashi Iwai /* standard HP-automute helper */
39355d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3936352f7f91STakashi Iwai {
3937352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
393892603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
393992603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
3940352f7f91STakashi Iwai 
394192603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
394292603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
394392603c59STakashi Iwai 		pins++;
394492603c59STakashi Iwai 		num_pins--;
394592603c59STakashi Iwai 	}
394692603c59STakashi Iwai 
394792603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
3948352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3949352f7f91STakashi Iwai 		return;
3950352f7f91STakashi Iwai 	call_update_outputs(codec);
3951352f7f91STakashi Iwai }
39525d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3953352f7f91STakashi Iwai 
3954352f7f91STakashi Iwai /* standard line-out-automute helper */
39555d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3956352f7f91STakashi Iwai {
3957352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3958352f7f91STakashi Iwai 
3959352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3960352f7f91STakashi Iwai 		return;
3961352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3962352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3963352f7f91STakashi Iwai 		return;
3964352f7f91STakashi Iwai 
3965352f7f91STakashi Iwai 	spec->line_jack_present =
3966352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3967352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3968352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3969352f7f91STakashi Iwai 		return;
3970352f7f91STakashi Iwai 	call_update_outputs(codec);
3971352f7f91STakashi Iwai }
39725d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3973352f7f91STakashi Iwai 
3974352f7f91STakashi Iwai /* standard mic auto-switch helper */
39755d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3976352f7f91STakashi Iwai {
3977352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3978352f7f91STakashi Iwai 	int i;
3979352f7f91STakashi Iwai 
3980352f7f91STakashi Iwai 	if (!spec->auto_mic)
3981352f7f91STakashi Iwai 		return;
3982352f7f91STakashi Iwai 
3983352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
39840b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
39850b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
39860b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
39870b4df931STakashi Iwai 			continue;
398860ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
3989352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3990352f7f91STakashi Iwai 			return;
3991352f7f91STakashi Iwai 		}
3992352f7f91STakashi Iwai 	}
3993352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
39941da177e4SLinus Torvalds }
39955d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
39961da177e4SLinus Torvalds 
399777afe0e9STakashi Iwai /* call appropriate hooks */
399877afe0e9STakashi Iwai static void call_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
399977afe0e9STakashi Iwai {
400077afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
400177afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
400277afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
400377afe0e9STakashi Iwai 	else
400477afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
400577afe0e9STakashi Iwai }
400677afe0e9STakashi Iwai 
400777afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
400877afe0e9STakashi Iwai 			       struct hda_jack_tbl *jack)
400977afe0e9STakashi Iwai {
401077afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
401177afe0e9STakashi Iwai 	if (spec->line_automute_hook)
401277afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
401377afe0e9STakashi Iwai 	else
401477afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
401577afe0e9STakashi Iwai }
401677afe0e9STakashi Iwai 
401777afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
401877afe0e9STakashi Iwai 				struct hda_jack_tbl *jack)
401977afe0e9STakashi Iwai {
402077afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
402177afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
402277afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
402377afe0e9STakashi Iwai 	else
402477afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
402577afe0e9STakashi Iwai }
402677afe0e9STakashi Iwai 
4027963afde9STakashi Iwai /* update jack retasking */
4028963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4029963afde9STakashi Iwai {
4030963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4031963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4032963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4033963afde9STakashi Iwai }
4034963afde9STakashi Iwai 
40351da177e4SLinus Torvalds /*
4036352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
40371da177e4SLinus Torvalds  */
4038352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4039352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4040352f7f91STakashi Iwai {
4041352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4042352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4043352f7f91STakashi Iwai 	static const char * const texts3[] = {
4044352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
40451da177e4SLinus Torvalds 	};
40461da177e4SLinus Torvalds 
4047352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4048352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4049352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4050352f7f91STakashi Iwai }
4051352f7f91STakashi Iwai 
4052352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4053352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4054352f7f91STakashi Iwai {
4055352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4056352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4057352f7f91STakashi Iwai 	unsigned int val = 0;
4058352f7f91STakashi Iwai 	if (spec->automute_speaker)
4059352f7f91STakashi Iwai 		val++;
4060352f7f91STakashi Iwai 	if (spec->automute_lo)
4061352f7f91STakashi Iwai 		val++;
4062352f7f91STakashi Iwai 
4063352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4064352f7f91STakashi Iwai 	return 0;
4065352f7f91STakashi Iwai }
4066352f7f91STakashi Iwai 
4067352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4068352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4069352f7f91STakashi Iwai {
4070352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4071352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4072352f7f91STakashi Iwai 
4073352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4074352f7f91STakashi Iwai 	case 0:
4075352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4076352f7f91STakashi Iwai 			return 0;
4077352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4078352f7f91STakashi Iwai 		spec->automute_lo = 0;
4079352f7f91STakashi Iwai 		break;
4080352f7f91STakashi Iwai 	case 1:
4081352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4082352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4083352f7f91STakashi Iwai 				return 0;
4084352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4085352f7f91STakashi Iwai 			spec->automute_lo = 0;
4086352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4087352f7f91STakashi Iwai 			if (spec->automute_lo)
4088352f7f91STakashi Iwai 				return 0;
4089352f7f91STakashi Iwai 			spec->automute_lo = 1;
4090352f7f91STakashi Iwai 		} else
4091352f7f91STakashi Iwai 			return -EINVAL;
4092352f7f91STakashi Iwai 		break;
4093352f7f91STakashi Iwai 	case 2:
4094352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4095352f7f91STakashi Iwai 			return -EINVAL;
4096352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4097352f7f91STakashi Iwai 			return 0;
4098352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4099352f7f91STakashi Iwai 		spec->automute_lo = 1;
4100352f7f91STakashi Iwai 		break;
4101352f7f91STakashi Iwai 	default:
4102352f7f91STakashi Iwai 		return -EINVAL;
4103352f7f91STakashi Iwai 	}
4104352f7f91STakashi Iwai 	call_update_outputs(codec);
4105352f7f91STakashi Iwai 	return 1;
4106352f7f91STakashi Iwai }
4107352f7f91STakashi Iwai 
4108352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4109352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4110352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4111352f7f91STakashi Iwai 	.info = automute_mode_info,
4112352f7f91STakashi Iwai 	.get = automute_mode_get,
4113352f7f91STakashi Iwai 	.put = automute_mode_put,
4114352f7f91STakashi Iwai };
4115352f7f91STakashi Iwai 
4116352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4117352f7f91STakashi Iwai {
4118352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4119352f7f91STakashi Iwai 
412012c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4121352f7f91STakashi Iwai 		return -ENOMEM;
4122352f7f91STakashi Iwai 	return 0;
4123352f7f91STakashi Iwai }
4124352f7f91STakashi Iwai 
4125352f7f91STakashi Iwai /*
4126352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4127352f7f91STakashi Iwai  * Set up appropriately if really supported
4128352f7f91STakashi Iwai  */
4129352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4130352f7f91STakashi Iwai {
4131352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4132352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4133352f7f91STakashi Iwai 	int present = 0;
4134352f7f91STakashi Iwai 	int i, err;
4135352f7f91STakashi Iwai 
4136f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4137f72706beSTakashi Iwai 		return 0;
4138f72706beSTakashi Iwai 
4139352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4140352f7f91STakashi Iwai 		present++;
4141352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4142352f7f91STakashi Iwai 		present++;
4143352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4144352f7f91STakashi Iwai 		present++;
4145352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4146352f7f91STakashi Iwai 		return 0;
4147352f7f91STakashi Iwai 
4148352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4149352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4150352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4151352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4152352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4153352f7f91STakashi Iwai 	}
4154352f7f91STakashi Iwai 
4155352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4156352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4157352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4158352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4159352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4160352f7f91STakashi Iwai 	}
4161352f7f91STakashi Iwai 
4162352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4163352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4164352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4165352f7f91STakashi Iwai 			continue;
4166352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
4167352f7f91STakashi Iwai 			    nid);
4168352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
416977afe0e9STakashi Iwai 						    call_hp_automute);
4170352f7f91STakashi Iwai 		spec->detect_hp = 1;
4171352f7f91STakashi Iwai 	}
4172352f7f91STakashi Iwai 
4173352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4174352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4175352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4176352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4177352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4178352f7f91STakashi Iwai 					continue;
4179352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
4180352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
4181352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
418277afe0e9STakashi Iwai 								    call_line_automute);
4183352f7f91STakashi Iwai 				spec->detect_lo = 1;
4184352f7f91STakashi Iwai 			}
4185352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4186352f7f91STakashi Iwai 	}
4187352f7f91STakashi Iwai 
4188352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4189352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4190352f7f91STakashi Iwai 
4191352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4192352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4193352f7f91STakashi Iwai 
4194352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4195352f7f91STakashi Iwai 		/* create a control for automute mode */
4196352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4197352f7f91STakashi Iwai 		if (err < 0)
4198352f7f91STakashi Iwai 			return err;
4199352f7f91STakashi Iwai 	}
4200352f7f91STakashi Iwai 	return 0;
4201352f7f91STakashi Iwai }
4202352f7f91STakashi Iwai 
4203352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4204352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4205352f7f91STakashi Iwai {
4206352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4207352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4208352f7f91STakashi Iwai 	int i;
4209352f7f91STakashi Iwai 
4210352f7f91STakashi Iwai 	imux = &spec->input_mux;
4211352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4212352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4213352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4214352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4215352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4216352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4217352f7f91STakashi Iwai 	}
4218352f7f91STakashi Iwai 
4219352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4220352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4221352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4222352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
4223352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
422477afe0e9STakashi Iwai 						    call_mic_autoswitch);
4225352f7f91STakashi Iwai 	return true;
4226352f7f91STakashi Iwai }
4227352f7f91STakashi Iwai 
4228352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4229352f7f91STakashi Iwai {
4230352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4231352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4232352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4233352f7f91STakashi Iwai }
4234352f7f91STakashi Iwai 
4235352f7f91STakashi Iwai /*
4236352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4237352f7f91STakashi Iwai  * Set up if really supported
4238352f7f91STakashi Iwai  */
4239352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4240352f7f91STakashi Iwai {
4241352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4242352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4243352f7f91STakashi Iwai 	unsigned int types;
4244352f7f91STakashi Iwai 	int i, num_pins;
4245352f7f91STakashi Iwai 
4246d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4247d12daf6fSTakashi Iwai 		return 0;
4248d12daf6fSTakashi Iwai 
4249352f7f91STakashi Iwai 	types = 0;
4250352f7f91STakashi Iwai 	num_pins = 0;
4251352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4252352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4253352f7f91STakashi Iwai 		unsigned int attr;
4254352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4255352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4256352f7f91STakashi Iwai 		if (types & (1 << attr))
4257352f7f91STakashi Iwai 			return 0; /* already occupied */
4258352f7f91STakashi Iwai 		switch (attr) {
4259352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4260352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4261352f7f91STakashi Iwai 				return 0; /* invalid type */
4262352f7f91STakashi Iwai 			break;
4263352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4264352f7f91STakashi Iwai 			return 0; /* invalid entry */
4265352f7f91STakashi Iwai 		default:
4266352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4267352f7f91STakashi Iwai 				return 0; /* invalid type */
4268352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4269352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4270352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4271352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4272352f7f91STakashi Iwai 				return 0; /* no unsol support */
4273352f7f91STakashi Iwai 			break;
4274352f7f91STakashi Iwai 		}
4275352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4276352f7f91STakashi Iwai 			return 0;
4277352f7f91STakashi Iwai 		types |= (1 << attr);
4278352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4279352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4280352f7f91STakashi Iwai 		num_pins++;
4281352f7f91STakashi Iwai 	}
4282352f7f91STakashi Iwai 
4283352f7f91STakashi Iwai 	if (num_pins < 2)
4284352f7f91STakashi Iwai 		return 0;
4285352f7f91STakashi Iwai 
4286352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4287352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4288352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4289352f7f91STakashi Iwai 	 */
4290352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4291352f7f91STakashi Iwai 	     compare_attr, NULL);
4292352f7f91STakashi Iwai 
4293352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4294352f7f91STakashi Iwai 		return 0;
4295352f7f91STakashi Iwai 
4296352f7f91STakashi Iwai 	spec->auto_mic = 1;
4297352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4298352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
4299352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4300352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4301352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4302352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4303352f7f91STakashi Iwai 
4304352f7f91STakashi Iwai 	return 0;
4305352f7f91STakashi Iwai }
4306352f7f91STakashi Iwai 
430755196fffSTakashi Iwai /* power_filter hook; make inactive widgets into power down */
430855196fffSTakashi Iwai static unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
430955196fffSTakashi Iwai 						  hda_nid_t nid,
431055196fffSTakashi Iwai 						  unsigned int power_state)
431155196fffSTakashi Iwai {
431255196fffSTakashi Iwai 	if (power_state != AC_PWRST_D0)
431355196fffSTakashi Iwai 		return power_state;
431455196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
431555196fffSTakashi Iwai 		return power_state;
4316b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
431755196fffSTakashi Iwai 		return power_state;
431855196fffSTakashi Iwai 	return AC_PWRST_D3;
431955196fffSTakashi Iwai }
432055196fffSTakashi Iwai 
4321ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4322ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4323ebb93c05STakashi Iwai {
4324ebb93c05STakashi Iwai 	int i, nums;
4325ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4326ebb93c05STakashi Iwai 	bool has_amp;
4327ebb93c05STakashi Iwai 
4328ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4329ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4330ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4331ebb93c05STakashi Iwai 		if (has_amp)
4332ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, mix,
4333ebb93c05STakashi Iwai 						 HDA_INPUT, i,
4334ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4335ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4336ebb93c05STakashi Iwai 			snd_hda_codec_amp_stereo(codec, conn[i],
4337ebb93c05STakashi Iwai 						 HDA_OUTPUT, 0,
4338ebb93c05STakashi Iwai 						 0xff, HDA_AMP_MUTE);
4339ebb93c05STakashi Iwai 	}
4340ebb93c05STakashi Iwai }
4341352f7f91STakashi Iwai 
43429eb413e5STakashi Iwai /*
43439eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
43449eb413e5STakashi Iwai  *
43459eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4346352f7f91STakashi Iwai  * or a negative error code
4347352f7f91STakashi Iwai  */
4348352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
43499eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4350352f7f91STakashi Iwai {
4351352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4352352f7f91STakashi Iwai 	int err;
4353352f7f91STakashi Iwai 
43541c70a583STakashi Iwai 	parse_user_hints(codec);
43551c70a583STakashi Iwai 
4356e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4357e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4358e4a395e7STakashi Iwai 
43599eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
43609eb413e5STakashi Iwai 		spec->autocfg = *cfg;
43619eb413e5STakashi Iwai 		cfg = &spec->autocfg;
43629eb413e5STakashi Iwai 	}
43639eb413e5STakashi Iwai 
436498bd1115STakashi Iwai 	if (!spec->main_out_badness)
436598bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
436698bd1115STakashi Iwai 	if (!spec->extra_out_badness)
436798bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
436898bd1115STakashi Iwai 
43696fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
43706fc4cb97SDavid Henningsson 
4371352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4372352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4373352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4374352f7f91STakashi Iwai 			spec->no_analog = 1;
4375352f7f91STakashi Iwai 			goto dig_only;
4376352f7f91STakashi Iwai 		}
4377352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
4378352f7f91STakashi Iwai 	}
4379352f7f91STakashi Iwai 
4380352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4381352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4382352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4383352f7f91STakashi Iwai 		/* use HP as primary out */
4384352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4385352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4386352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4387352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4388352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4389352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4390352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4391352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4392352f7f91STakashi Iwai 	}
4393352f7f91STakashi Iwai 
4394352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4395352f7f91STakashi Iwai 	if (err < 0)
4396352f7f91STakashi Iwai 		return err;
4397352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4398352f7f91STakashi Iwai 	if (err < 0)
4399352f7f91STakashi Iwai 		return err;
4400352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4401352f7f91STakashi Iwai 	if (err < 0)
4402352f7f91STakashi Iwai 		return err;
4403352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4404352f7f91STakashi Iwai 	if (err < 0)
4405352f7f91STakashi Iwai 		return err;
4406352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
4407352f7f91STakashi Iwai 	if (err < 0)
4408352f7f91STakashi Iwai 		return err;
440938cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
441038cf6f1aSTakashi Iwai 	if (err < 0)
441138cf6f1aSTakashi Iwai 		return err;
4412c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
4413c30aa7b2STakashi Iwai 	if (err < 0)
4414c30aa7b2STakashi Iwai 		return err;
4415967303daSTakashi Iwai 	err = create_hp_mic(codec);
4416352f7f91STakashi Iwai 	if (err < 0)
4417352f7f91STakashi Iwai 		return err;
4418352f7f91STakashi Iwai 	err = create_input_ctls(codec);
4419352f7f91STakashi Iwai 	if (err < 0)
4420352f7f91STakashi Iwai 		return err;
4421352f7f91STakashi Iwai 
4422a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
4423a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
4424a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4425a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4426a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
4427a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4428a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
4429a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
4430352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
4431352f7f91STakashi Iwai 					  spec->const_channel_count);
4432352f7f91STakashi Iwai 
4433352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
4434352f7f91STakashi Iwai 	if (err < 0)
4435352f7f91STakashi Iwai 		return err;
4436352f7f91STakashi Iwai 
4437352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
4438352f7f91STakashi Iwai 	if (err < 0)
4439352f7f91STakashi Iwai 		return err;
4440352f7f91STakashi Iwai 
4441352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
4442352f7f91STakashi Iwai 	if (err < 0)
4443352f7f91STakashi Iwai 		return err;
4444352f7f91STakashi Iwai 
4445352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
4446352f7f91STakashi Iwai 	if (err < 0)
4447352f7f91STakashi Iwai 		return err;
4448352f7f91STakashi Iwai 
4449352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
4450352f7f91STakashi Iwai 	if (err < 0)
4451352f7f91STakashi Iwai 		return err;
4452352f7f91STakashi Iwai 
4453ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
4454ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
4455ced4cefcSTakashi Iwai 	 */
4456ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
4457ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
4458ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
4459ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
4460ced4cefcSTakashi Iwai 		if (err < 0)
4461ced4cefcSTakashi Iwai 			return err;
4462ced4cefcSTakashi Iwai 	}
4463ced4cefcSTakashi Iwai 
4464f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
4465978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4466978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
4467978e77e7STakashi Iwai 						    cfg->line_out_pins);
4468978e77e7STakashi Iwai 			if (err < 0)
4469978e77e7STakashi Iwai 				return err;
4470978e77e7STakashi Iwai 		}
4471978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4472978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
4473978e77e7STakashi Iwai 						    cfg->hp_pins);
4474978e77e7STakashi Iwai 			if (err < 0)
4475978e77e7STakashi Iwai 				return err;
4476978e77e7STakashi Iwai 		}
4477978e77e7STakashi Iwai 	}
4478978e77e7STakashi Iwai 
4479ebb93c05STakashi Iwai 	/* mute all aamix input initially */
4480ebb93c05STakashi Iwai 	if (spec->mixer_nid)
4481ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
4482ebb93c05STakashi Iwai 
4483352f7f91STakashi Iwai  dig_only:
4484352f7f91STakashi Iwai 	parse_digital(codec);
4485352f7f91STakashi Iwai 
448655196fffSTakashi Iwai 	if (spec->power_down_unused)
448755196fffSTakashi Iwai 		codec->power_filter = snd_hda_gen_path_power_filter;
448855196fffSTakashi Iwai 
44897504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
44907504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
44917504b6cdSTakashi Iwai 		if (err < 0)
44927504b6cdSTakashi Iwai 			return err;
44937504b6cdSTakashi Iwai 	}
44947504b6cdSTakashi Iwai 
4495352f7f91STakashi Iwai 	return 1;
4496352f7f91STakashi Iwai }
4497352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
4498352f7f91STakashi Iwai 
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai /*
4501352f7f91STakashi Iwai  * Build control elements
4502352f7f91STakashi Iwai  */
4503352f7f91STakashi Iwai 
4504352f7f91STakashi Iwai /* slave controls for virtual master */
4505352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
4506352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
4507352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
4508352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
4509ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
4510ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
4511ee79c69aSTakashi Iwai 	"Headphone Side",
4512352f7f91STakashi Iwai 	NULL,
4513352f7f91STakashi Iwai };
4514352f7f91STakashi Iwai 
4515352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
4516352f7f91STakashi Iwai {
4517352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4518352f7f91STakashi Iwai 	int err;
4519352f7f91STakashi Iwai 
452036502d02STakashi Iwai 	if (spec->kctls.used) {
4521352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
4522352f7f91STakashi Iwai 		if (err < 0)
4523352f7f91STakashi Iwai 			return err;
452436502d02STakashi Iwai 	}
4525352f7f91STakashi Iwai 
4526352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
4527352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
4528352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4529352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
4530352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
4531352f7f91STakashi Iwai 		if (err < 0)
4532352f7f91STakashi Iwai 			return err;
4533352f7f91STakashi Iwai 		if (!spec->no_analog) {
4534352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
4535352f7f91STakashi Iwai 							    &spec->multiout);
4536352f7f91STakashi Iwai 			if (err < 0)
4537352f7f91STakashi Iwai 				return err;
4538352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
4539352f7f91STakashi Iwai 		}
4540352f7f91STakashi Iwai 	}
4541352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
4542352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
4543352f7f91STakashi Iwai 		if (err < 0)
4544352f7f91STakashi Iwai 			return err;
4545352f7f91STakashi Iwai 	}
4546352f7f91STakashi Iwai 
4547352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
4548352f7f91STakashi Iwai 	if (!spec->no_analog &&
4549352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
4550352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
45517a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
4552352f7f91STakashi Iwai 					  "Playback Volume");
4553352f7f91STakashi Iwai 		if (err < 0)
4554352f7f91STakashi Iwai 			return err;
4555352f7f91STakashi Iwai 	}
4556352f7f91STakashi Iwai 	if (!spec->no_analog &&
4557352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
4558352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
4559352f7f91STakashi Iwai 					    NULL, slave_pfxs,
4560352f7f91STakashi Iwai 					    "Playback Switch",
4561352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
4562352f7f91STakashi Iwai 		if (err < 0)
4563352f7f91STakashi Iwai 			return err;
4564b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
4565fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
4566fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
4567b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4568b63eae0aSTakashi Iwai 		}
4569352f7f91STakashi Iwai 	}
4570352f7f91STakashi Iwai 
4571352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
4572352f7f91STakashi Iwai 
4573352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
4574352f7f91STakashi Iwai 	if (err < 0)
4575352f7f91STakashi Iwai 		return err;
4576352f7f91STakashi Iwai 
4577352f7f91STakashi Iwai 	return 0;
4578352f7f91STakashi Iwai }
4579352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
4580352f7f91STakashi Iwai 
4581352f7f91STakashi Iwai 
4582352f7f91STakashi Iwai /*
4583352f7f91STakashi Iwai  * PCM definitions
4584352f7f91STakashi Iwai  */
4585352f7f91STakashi Iwai 
4586e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
4587e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
4588e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
4589e6b85f3cSTakashi Iwai 				   int action)
4590e6b85f3cSTakashi Iwai {
4591e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4592e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
4593e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
4594e6b85f3cSTakashi Iwai }
4595e6b85f3cSTakashi Iwai 
4596ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
4597ac2e8736STakashi Iwai 				  struct hda_codec *codec,
4598ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
4599ac2e8736STakashi Iwai 				  int action)
4600ac2e8736STakashi Iwai {
4601ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4602ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
4603ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
4604ac2e8736STakashi Iwai }
4605ac2e8736STakashi Iwai 
4606352f7f91STakashi Iwai /*
4607352f7f91STakashi Iwai  * Analog playback callbacks
4608352f7f91STakashi Iwai  */
4609352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
4610352f7f91STakashi Iwai 			     struct hda_codec *codec,
4611352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
4612352f7f91STakashi Iwai {
4613352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
461438cf6f1aSTakashi Iwai 	int err;
461538cf6f1aSTakashi Iwai 
461638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
461738cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
461838cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
4619352f7f91STakashi Iwai 					     hinfo);
4620e6b85f3cSTakashi Iwai 	if (!err) {
462138cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
4622e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4623e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
4624e6b85f3cSTakashi Iwai 	}
462538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
462638cf6f1aSTakashi Iwai 	return err;
4627352f7f91STakashi Iwai }
4628352f7f91STakashi Iwai 
4629352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
463097ec558aSTakashi Iwai 				struct hda_codec *codec,
463197ec558aSTakashi Iwai 				unsigned int stream_tag,
463297ec558aSTakashi Iwai 				unsigned int format,
463397ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
463497ec558aSTakashi Iwai {
4635352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4636e6b85f3cSTakashi Iwai 	int err;
4637e6b85f3cSTakashi Iwai 
4638e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4639352f7f91STakashi Iwai 					       stream_tag, format, substream);
4640e6b85f3cSTakashi Iwai 	if (!err)
4641e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4642e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4643e6b85f3cSTakashi Iwai 	return err;
4644352f7f91STakashi Iwai }
464597ec558aSTakashi Iwai 
4646352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4647352f7f91STakashi Iwai 				struct hda_codec *codec,
4648352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4649352f7f91STakashi Iwai {
4650352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4651e6b85f3cSTakashi Iwai 	int err;
4652e6b85f3cSTakashi Iwai 
4653e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4654e6b85f3cSTakashi Iwai 	if (!err)
4655e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4656e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4657e6b85f3cSTakashi Iwai 	return err;
4658352f7f91STakashi Iwai }
4659352f7f91STakashi Iwai 
466038cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
466138cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
466238cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
466338cf6f1aSTakashi Iwai {
466438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
466538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
466638cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4667e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4668e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
466938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
467038cf6f1aSTakashi Iwai 	return 0;
467138cf6f1aSTakashi Iwai }
467238cf6f1aSTakashi Iwai 
4673ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4674ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4675ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4676ac2e8736STakashi Iwai {
4677ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4678ac2e8736STakashi Iwai 	return 0;
4679ac2e8736STakashi Iwai }
4680ac2e8736STakashi Iwai 
4681ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4682ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4683ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4684ac2e8736STakashi Iwai 			       unsigned int format,
4685ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4686ac2e8736STakashi Iwai {
4687ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4688ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4689ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4690ac2e8736STakashi Iwai 	return 0;
4691ac2e8736STakashi Iwai }
4692ac2e8736STakashi Iwai 
4693ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4694ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4695ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4696ac2e8736STakashi Iwai {
4697ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4698ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4699ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4700ac2e8736STakashi Iwai 	return 0;
4701ac2e8736STakashi Iwai }
4702ac2e8736STakashi Iwai 
4703ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4704ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4705ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4706ac2e8736STakashi Iwai {
4707ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4708ac2e8736STakashi Iwai 	return 0;
4709ac2e8736STakashi Iwai }
4710ac2e8736STakashi Iwai 
471138cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
471238cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
471338cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
471438cf6f1aSTakashi Iwai {
471538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
471638cf6f1aSTakashi Iwai 	int err = 0;
471738cf6f1aSTakashi Iwai 
471838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
471938cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
472038cf6f1aSTakashi Iwai 		err = -EBUSY;
472138cf6f1aSTakashi Iwai 	else
472238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4723e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4724e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
472538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
472638cf6f1aSTakashi Iwai 	return err;
472738cf6f1aSTakashi Iwai }
472838cf6f1aSTakashi Iwai 
472938cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
473038cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
473138cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
473238cf6f1aSTakashi Iwai {
473338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
473438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
473538cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4736e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4737e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
473838cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
473938cf6f1aSTakashi Iwai 	return 0;
474038cf6f1aSTakashi Iwai }
474138cf6f1aSTakashi Iwai 
4742e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4743e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4744e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4745e6b85f3cSTakashi Iwai 				    unsigned int format,
4746e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4747e6b85f3cSTakashi Iwai {
4748e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4749e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4750e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4751e6b85f3cSTakashi Iwai 	return 0;
4752e6b85f3cSTakashi Iwai }
4753e6b85f3cSTakashi Iwai 
4754e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4755e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4756e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4757e6b85f3cSTakashi Iwai {
4758e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4759e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4760e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4761e6b85f3cSTakashi Iwai 	return 0;
4762e6b85f3cSTakashi Iwai }
4763e6b85f3cSTakashi Iwai 
4764352f7f91STakashi Iwai /*
4765352f7f91STakashi Iwai  * Digital out
4766352f7f91STakashi Iwai  */
4767352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4768352f7f91STakashi Iwai 				 struct hda_codec *codec,
4769352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4770352f7f91STakashi Iwai {
4771352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4772352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4773352f7f91STakashi Iwai }
4774352f7f91STakashi Iwai 
4775352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4776352f7f91STakashi Iwai 				    struct hda_codec *codec,
4777352f7f91STakashi Iwai 				    unsigned int stream_tag,
4778352f7f91STakashi Iwai 				    unsigned int format,
4779352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4780352f7f91STakashi Iwai {
4781352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4782352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4783352f7f91STakashi Iwai 					     stream_tag, format, substream);
4784352f7f91STakashi Iwai }
4785352f7f91STakashi Iwai 
4786352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4787352f7f91STakashi Iwai 				    struct hda_codec *codec,
4788352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4789352f7f91STakashi Iwai {
4790352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4791352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4792352f7f91STakashi Iwai }
4793352f7f91STakashi Iwai 
4794352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4795352f7f91STakashi Iwai 				  struct hda_codec *codec,
4796352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4797352f7f91STakashi Iwai {
4798352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4799352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4800352f7f91STakashi Iwai }
4801352f7f91STakashi Iwai 
4802352f7f91STakashi Iwai /*
4803352f7f91STakashi Iwai  * Analog capture
4804352f7f91STakashi Iwai  */
4805ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4806ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4807ac2e8736STakashi Iwai 
4808352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4809352f7f91STakashi Iwai 				   struct hda_codec *codec,
4810352f7f91STakashi Iwai 				   unsigned int stream_tag,
4811352f7f91STakashi Iwai 				   unsigned int format,
4812352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4813352f7f91STakashi Iwai {
4814352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4815352f7f91STakashi Iwai 
4816352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
481797ec558aSTakashi Iwai 				   stream_tag, 0, format);
4818ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4819ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
482097ec558aSTakashi Iwai 	return 0;
482197ec558aSTakashi Iwai }
482297ec558aSTakashi Iwai 
4823352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
482497ec558aSTakashi Iwai 				   struct hda_codec *codec,
482597ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
482697ec558aSTakashi Iwai {
4827352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
482897ec558aSTakashi Iwai 
4829352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4830352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4831ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4832ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
483397ec558aSTakashi Iwai 	return 0;
483497ec558aSTakashi Iwai }
483597ec558aSTakashi Iwai 
4836352f7f91STakashi Iwai /*
4837352f7f91STakashi Iwai  */
4838352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4839352f7f91STakashi Iwai 	.substreams = 1,
4840352f7f91STakashi Iwai 	.channels_min = 2,
4841352f7f91STakashi Iwai 	.channels_max = 8,
4842352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4843352f7f91STakashi Iwai 	.ops = {
4844352f7f91STakashi Iwai 		.open = playback_pcm_open,
484538cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4846352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4847352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4848352f7f91STakashi Iwai 	},
4849352f7f91STakashi Iwai };
4850352f7f91STakashi Iwai 
4851352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4852352f7f91STakashi Iwai 	.substreams = 1,
4853352f7f91STakashi Iwai 	.channels_min = 2,
4854352f7f91STakashi Iwai 	.channels_max = 2,
4855352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4856ac2e8736STakashi Iwai 	.ops = {
4857ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4858ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4859ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4860ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4861ac2e8736STakashi Iwai 	},
4862352f7f91STakashi Iwai };
4863352f7f91STakashi Iwai 
4864352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4865352f7f91STakashi Iwai 	.substreams = 1,
4866352f7f91STakashi Iwai 	.channels_min = 2,
4867352f7f91STakashi Iwai 	.channels_max = 2,
4868352f7f91STakashi Iwai 	/* NID is set in build_pcms */
486938cf6f1aSTakashi Iwai 	.ops = {
487038cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4871e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4872e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4873e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
487438cf6f1aSTakashi Iwai 	},
4875352f7f91STakashi Iwai };
4876352f7f91STakashi Iwai 
4877352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4878352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4879352f7f91STakashi Iwai 	.channels_min = 2,
4880352f7f91STakashi Iwai 	.channels_max = 2,
4881352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4882352f7f91STakashi Iwai 	.ops = {
4883ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4884ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4885352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4886352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4887352f7f91STakashi Iwai 	},
4888352f7f91STakashi Iwai };
4889352f7f91STakashi Iwai 
4890352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4891352f7f91STakashi Iwai 	.substreams = 1,
4892352f7f91STakashi Iwai 	.channels_min = 2,
4893352f7f91STakashi Iwai 	.channels_max = 2,
4894352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4895352f7f91STakashi Iwai 	.ops = {
4896352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4897352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4898352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4899352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4900352f7f91STakashi Iwai 	},
4901352f7f91STakashi Iwai };
4902352f7f91STakashi Iwai 
4903352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4904352f7f91STakashi Iwai 	.substreams = 1,
4905352f7f91STakashi Iwai 	.channels_min = 2,
4906352f7f91STakashi Iwai 	.channels_max = 2,
4907352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4908352f7f91STakashi Iwai };
4909352f7f91STakashi Iwai 
4910352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4911352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4912352f7f91STakashi Iwai 	.substreams = 0,
4913352f7f91STakashi Iwai 	.channels_min = 0,
4914352f7f91STakashi Iwai 	.channels_max = 0,
4915352f7f91STakashi Iwai };
4916352f7f91STakashi Iwai 
4917352f7f91STakashi Iwai /*
4918352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4919352f7f91STakashi Iwai  */
4920352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
49211da177e4SLinus Torvalds {
4922352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4923352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
49241da177e4SLinus Torvalds 
4925352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4926352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4927352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4928352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4929352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4930352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4931352f7f91STakashi Iwai 					   spec->cur_adc_format);
4932352f7f91STakashi Iwai 		return true;
4933352f7f91STakashi Iwai 	}
4934352f7f91STakashi Iwai 	return false;
4935352f7f91STakashi Iwai }
4936352f7f91STakashi Iwai 
4937352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4938352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4939352f7f91STakashi Iwai 				       struct hda_codec *codec,
4940352f7f91STakashi Iwai 				       unsigned int stream_tag,
4941352f7f91STakashi Iwai 				       unsigned int format,
4942352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4943352f7f91STakashi Iwai {
4944352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4945352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4946352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4947352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4948352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
49491da177e4SLinus Torvalds 	return 0;
49501da177e4SLinus Torvalds }
49511da177e4SLinus Torvalds 
4952352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4953352f7f91STakashi Iwai 				       struct hda_codec *codec,
4954352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4955352f7f91STakashi Iwai {
4956352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4957352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4958352f7f91STakashi Iwai 	spec->cur_adc = 0;
4959352f7f91STakashi Iwai 	return 0;
4960352f7f91STakashi Iwai }
4961352f7f91STakashi Iwai 
4962352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4963352f7f91STakashi Iwai 	.substreams = 1,
4964352f7f91STakashi Iwai 	.channels_min = 2,
4965352f7f91STakashi Iwai 	.channels_max = 2,
4966352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4967352f7f91STakashi Iwai 	.ops = {
4968352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4969352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4970352f7f91STakashi Iwai 	},
4971352f7f91STakashi Iwai };
4972352f7f91STakashi Iwai 
4973f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4974f873e536STakashi Iwai 				 const char *chip_name)
4975f873e536STakashi Iwai {
4976f873e536STakashi Iwai 	char *p;
4977f873e536STakashi Iwai 
4978f873e536STakashi Iwai 	if (*str)
4979f873e536STakashi Iwai 		return;
4980f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4981f873e536STakashi Iwai 
4982f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4983f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4984f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4985f873e536STakashi Iwai 			*p = 0;
4986f873e536STakashi Iwai 			break;
4987f873e536STakashi Iwai 		}
4988f873e536STakashi Iwai 	}
4989f873e536STakashi Iwai 	strlcat(str, sfx, len);
4990f873e536STakashi Iwai }
4991f873e536STakashi Iwai 
4992352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4993352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4994352f7f91STakashi Iwai {
4995352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4996352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4997352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4998352f7f91STakashi Iwai 	bool have_multi_adcs;
4999352f7f91STakashi Iwai 
50001da177e4SLinus Torvalds 	codec->num_pcms = 1;
50011da177e4SLinus Torvalds 	codec->pcm_info = info;
50021da177e4SLinus Torvalds 
5003352f7f91STakashi Iwai 	if (spec->no_analog)
5004352f7f91STakashi Iwai 		goto skip_analog;
5005352f7f91STakashi Iwai 
5006f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5007f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
5008f873e536STakashi Iwai 			     " Analog", codec->chip_name);
5009352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
5010352f7f91STakashi Iwai 
5011352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5012352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
5013352f7f91STakashi Iwai 		if (!p)
5014352f7f91STakashi Iwai 			p = &pcm_analog_playback;
5015352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5016352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
5017352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5018352f7f91STakashi Iwai 			spec->multiout.max_channels;
5019352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5020352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5021352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5022352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5023352f7f91STakashi Iwai 	}
5024352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5025352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
5026352f7f91STakashi Iwai 		if (!p) {
5027352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
5028352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
5029352f7f91STakashi Iwai 			else
5030352f7f91STakashi Iwai 				p = &pcm_analog_capture;
5031352f7f91STakashi Iwai 		}
5032352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5033352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
5034352f7f91STakashi Iwai 	}
5035352f7f91STakashi Iwai 
5036352f7f91STakashi Iwai  skip_analog:
5037352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5038352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5039f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5040352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
5041f873e536STakashi Iwai 				     " Digital", codec->chip_name);
5042352f7f91STakashi Iwai 		codec->num_pcms = 2;
5043352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
5044352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
5045352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
5046352f7f91STakashi Iwai 		if (spec->dig_out_type)
5047352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5048352f7f91STakashi Iwai 		else
5049352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5050352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
5051352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
5052352f7f91STakashi Iwai 			if (!p)
5053352f7f91STakashi Iwai 				p = &pcm_digital_playback;
5054352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5055352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
5056352f7f91STakashi Iwai 		}
5057352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
5058352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
5059352f7f91STakashi Iwai 			if (!p)
5060352f7f91STakashi Iwai 				p = &pcm_digital_capture;
5061352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5062352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
5063352f7f91STakashi Iwai 		}
5064352f7f91STakashi Iwai 	}
5065352f7f91STakashi Iwai 
5066352f7f91STakashi Iwai 	if (spec->no_analog)
5067352f7f91STakashi Iwai 		return 0;
5068352f7f91STakashi Iwai 
5069352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5070352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5071352f7f91STakashi Iwai 	 */
5072352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5073352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5074352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5075352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5076a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5077a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
5078a607148fSTakashi Iwai 			     " Alt Analog", codec->chip_name);
5079352f7f91STakashi Iwai 		codec->num_pcms = 3;
5080352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
5081a607148fSTakashi Iwai 		info->name = spec->stream_name_alt_analog;
5082352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
5083352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
5084352f7f91STakashi Iwai 			if (!p)
5085352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
5086352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
5087352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
5088352f7f91STakashi Iwai 				spec->alt_dac_nid;
5089352f7f91STakashi Iwai 		} else {
5090352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
5091352f7f91STakashi Iwai 				pcm_null_stream;
5092352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
5093352f7f91STakashi Iwai 		}
5094352f7f91STakashi Iwai 		if (have_multi_adcs) {
5095352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
5096352f7f91STakashi Iwai 			if (!p)
5097352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
5098352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
5099352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
5100352f7f91STakashi Iwai 				spec->adc_nids[1];
5101352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5102352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5103352f7f91STakashi Iwai 		} else {
5104352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
5105352f7f91STakashi Iwai 				pcm_null_stream;
5106352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
5107352f7f91STakashi Iwai 		}
51081da177e4SLinus Torvalds 	}
51091da177e4SLinus Torvalds 
51101da177e4SLinus Torvalds 	return 0;
51111da177e4SLinus Torvalds }
5112352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
5113352f7f91STakashi Iwai 
5114352f7f91STakashi Iwai 
5115352f7f91STakashi Iwai /*
5116352f7f91STakashi Iwai  * Standard auto-parser initializations
5117352f7f91STakashi Iwai  */
5118352f7f91STakashi Iwai 
5119d4156930STakashi Iwai /* configure the given path as a proper output */
51202c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5121352f7f91STakashi Iwai {
5122352f7f91STakashi Iwai 	struct nid_path *path;
5123d4156930STakashi Iwai 	hda_nid_t pin;
5124352f7f91STakashi Iwai 
5125196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5126d4156930STakashi Iwai 	if (!path || !path->depth)
5127352f7f91STakashi Iwai 		return;
5128d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
51292c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
513065033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
513165033cc8STakashi Iwai 			      aamix_default(codec->spec));
5132e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5133352f7f91STakashi Iwai }
5134352f7f91STakashi Iwai 
5135352f7f91STakashi Iwai /* initialize primary output paths */
5136352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5137352f7f91STakashi Iwai {
5138352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5139352f7f91STakashi Iwai 	int i;
5140352f7f91STakashi Iwai 
5141d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
51422c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5143352f7f91STakashi Iwai }
5144352f7f91STakashi Iwai 
5145db23fd19STakashi Iwai 
51462c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5147352f7f91STakashi Iwai {
5148352f7f91STakashi Iwai 	int i;
5149352f7f91STakashi Iwai 
5150d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
51512c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5152352f7f91STakashi Iwai }
5153db23fd19STakashi Iwai 
5154db23fd19STakashi Iwai /* initialize hp and speaker paths */
5155db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5156db23fd19STakashi Iwai {
5157db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5158db23fd19STakashi Iwai 
5159db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
51602c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5161db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5162db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
51632c12c30dSTakashi Iwai 				 spec->speaker_paths);
5164352f7f91STakashi Iwai }
5165352f7f91STakashi Iwai 
5166352f7f91STakashi Iwai /* initialize multi-io paths */
5167352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5168352f7f91STakashi Iwai {
5169352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5170352f7f91STakashi Iwai 	int i;
5171352f7f91STakashi Iwai 
5172352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5173352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5174352f7f91STakashi Iwai 		struct nid_path *path;
5175196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5176352f7f91STakashi Iwai 		if (!path)
5177352f7f91STakashi Iwai 			continue;
5178352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5179352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
51802c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
518165033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
518265033cc8STakashi Iwai 				      aamix_default(spec));
5183352f7f91STakashi Iwai 	}
5184352f7f91STakashi Iwai }
5185352f7f91STakashi Iwai 
5186352f7f91STakashi Iwai /* set up input pins and loopback paths */
5187352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5188352f7f91STakashi Iwai {
5189352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5190352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5191352f7f91STakashi Iwai 	int i;
5192352f7f91STakashi Iwai 
5193352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5194352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5195352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
51962c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5197352f7f91STakashi Iwai 
5198352f7f91STakashi Iwai 		/* init loopback inputs */
5199352f7f91STakashi Iwai 		if (spec->mixer_nid) {
52003e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
52013e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5202352f7f91STakashi Iwai 		}
5203352f7f91STakashi Iwai 	}
5204352f7f91STakashi Iwai }
5205352f7f91STakashi Iwai 
5206352f7f91STakashi Iwai /* initialize ADC paths */
5207352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5208352f7f91STakashi Iwai {
5209352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5210352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5211352f7f91STakashi Iwai 	struct nid_path *path;
5212352f7f91STakashi Iwai 	int i, c, nums;
5213352f7f91STakashi Iwai 
5214352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5215352f7f91STakashi Iwai 		nums = 1;
5216352f7f91STakashi Iwai 	else
5217352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5218352f7f91STakashi Iwai 
5219352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5220352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5221c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5222352f7f91STakashi Iwai 			if (path) {
5223352f7f91STakashi Iwai 				bool active = path->active;
5224352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5225352f7f91STakashi Iwai 					active = true;
5226352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5227352f7f91STakashi Iwai 			}
5228352f7f91STakashi Iwai 		}
5229967303daSTakashi Iwai 		if (spec->hp_mic)
5230967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5231352f7f91STakashi Iwai 	}
5232352f7f91STakashi Iwai 
5233352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
5234a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
5235352f7f91STakashi Iwai }
5236352f7f91STakashi Iwai 
5237352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5238352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5239352f7f91STakashi Iwai {
5240352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5241352f7f91STakashi Iwai 	int i;
5242352f7f91STakashi Iwai 	hda_nid_t pin;
5243352f7f91STakashi Iwai 
5244d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
52452c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5246352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
52472430d7b7STakashi Iwai 	if (pin) {
52482c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
52493e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
52502430d7b7STakashi Iwai 	}
5251352f7f91STakashi Iwai }
5252352f7f91STakashi Iwai 
5253973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5254973e4972STakashi Iwai  * invalid unsol tags by some reason
5255973e4972STakashi Iwai  */
5256973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5257973e4972STakashi Iwai {
5258973e4972STakashi Iwai 	int i;
5259973e4972STakashi Iwai 
5260973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
5261973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
5262973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5263973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5264973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5265973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
5266973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5267973e4972STakashi Iwai 	}
5268973e4972STakashi Iwai }
5269973e4972STakashi Iwai 
52705187ac16STakashi Iwai /*
52715187ac16STakashi Iwai  * initialize the generic spec;
52725187ac16STakashi Iwai  * this can be put as patch_ops.init function
52735187ac16STakashi Iwai  */
5274352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5275352f7f91STakashi Iwai {
5276352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5277352f7f91STakashi Iwai 
5278352f7f91STakashi Iwai 	if (spec->init_hook)
5279352f7f91STakashi Iwai 		spec->init_hook(codec);
5280352f7f91STakashi Iwai 
5281352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
5282352f7f91STakashi Iwai 
52833bbcd274STakashi Iwai 	codec->cached_write = 1;
52843bbcd274STakashi Iwai 
5285352f7f91STakashi Iwai 	init_multi_out(codec);
5286352f7f91STakashi Iwai 	init_extra_out(codec);
5287352f7f91STakashi Iwai 	init_multi_io(codec);
5288352f7f91STakashi Iwai 	init_analog_input(codec);
5289352f7f91STakashi Iwai 	init_input_src(codec);
5290352f7f91STakashi Iwai 	init_digital(codec);
5291352f7f91STakashi Iwai 
5292973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5293973e4972STakashi Iwai 
5294352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5295a5cc2509STakashi Iwai 	update_automute_all(codec);
5296352f7f91STakashi Iwai 
5297dc870f38STakashi Iwai 	snd_hda_codec_flush_cache(codec);
52983bbcd274STakashi Iwai 
5299352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5300352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5301352f7f91STakashi Iwai 
5302352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5303352f7f91STakashi Iwai 	return 0;
5304352f7f91STakashi Iwai }
5305fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
5306fce52a3bSTakashi Iwai 
53075187ac16STakashi Iwai /*
53085187ac16STakashi Iwai  * free the generic spec;
53095187ac16STakashi Iwai  * this can be put as patch_ops.free function
53105187ac16STakashi Iwai  */
5311fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5312fce52a3bSTakashi Iwai {
53137504b6cdSTakashi Iwai 	snd_hda_detach_beep_device(codec);
5314fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5315fce52a3bSTakashi Iwai 	kfree(codec->spec);
5316fce52a3bSTakashi Iwai 	codec->spec = NULL;
5317fce52a3bSTakashi Iwai }
5318fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
5319fce52a3bSTakashi Iwai 
5320fce52a3bSTakashi Iwai #ifdef CONFIG_PM
53215187ac16STakashi Iwai /*
53225187ac16STakashi Iwai  * check the loopback power save state;
53235187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
53245187ac16STakashi Iwai  */
5325fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
5326fce52a3bSTakashi Iwai {
5327fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5328fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
5329fce52a3bSTakashi Iwai }
5330fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
5331fce52a3bSTakashi Iwai #endif
5332352f7f91STakashi Iwai 
5333352f7f91STakashi Iwai 
5334352f7f91STakashi Iwai /*
5335352f7f91STakashi Iwai  * the generic codec support
5336352f7f91STakashi Iwai  */
53371da177e4SLinus Torvalds 
5338352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
5339352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
5340352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
5341352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
5342fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
5343352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
534483012a7cSTakashi Iwai #ifdef CONFIG_PM
5345fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
5346cb53c626STakashi Iwai #endif
53471da177e4SLinus Torvalds };
53481da177e4SLinus Torvalds 
53491da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
53501da177e4SLinus Torvalds {
5351352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
53521da177e4SLinus Torvalds 	int err;
53531da177e4SLinus Torvalds 
5354e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5355352f7f91STakashi Iwai 	if (!spec)
53561da177e4SLinus Torvalds 		return -ENOMEM;
5357352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
53581da177e4SLinus Torvalds 	codec->spec = spec;
53591da177e4SLinus Torvalds 
53609eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
53619eb413e5STakashi Iwai 	if (err < 0)
53629eb413e5STakashi Iwai 		return err;
53639eb413e5STakashi Iwai 
53649eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
5365352f7f91STakashi Iwai 	if (err < 0)
53661da177e4SLinus Torvalds 		goto error;
53671da177e4SLinus Torvalds 
53681da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
53691da177e4SLinus Torvalds 	return 0;
53701da177e4SLinus Torvalds 
53711da177e4SLinus Torvalds error:
5372fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
53731da177e4SLinus Torvalds 	return err;
53741da177e4SLinus Torvalds }
5375fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
5376