xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 9dba205b)
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>
27f873e536STakashi Iwai #include <linux/ctype.h>
28f873e536STakashi Iwai #include <linux/string.h>
2929476558STakashi Iwai #include <linux/bitops.h>
301da177e4SLinus Torvalds #include <sound/core.h>
31352f7f91STakashi Iwai #include <sound/jack.h>
321da177e4SLinus Torvalds #include "hda_codec.h"
331da177e4SLinus Torvalds #include "hda_local.h"
34352f7f91STakashi Iwai #include "hda_auto_parser.h"
35352f7f91STakashi Iwai #include "hda_jack.h"
36352f7f91STakashi Iwai #include "hda_generic.h"
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds 
39352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
40352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
411da177e4SLinus Torvalds {
42352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
43352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
4438cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
45352f7f91STakashi Iwai 	return 0;
46352f7f91STakashi Iwai }
47352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
481da177e4SLinus Torvalds 
4912c93df6STakashi Iwai struct snd_kcontrol_new *
5012c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
51352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
52352f7f91STakashi Iwai {
53352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
54352f7f91STakashi Iwai 	if (!knew)
55352f7f91STakashi Iwai 		return NULL;
56352f7f91STakashi Iwai 	*knew = *temp;
57352f7f91STakashi Iwai 	if (name)
58352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
59352f7f91STakashi Iwai 	else if (knew->name)
60352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
61352f7f91STakashi Iwai 	if (!knew->name)
62352f7f91STakashi Iwai 		return NULL;
63352f7f91STakashi Iwai 	return knew;
64352f7f91STakashi Iwai }
6512c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
66352f7f91STakashi Iwai 
67352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
68352f7f91STakashi Iwai {
69352f7f91STakashi Iwai 	if (spec->kctls.list) {
70352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
71352f7f91STakashi Iwai 		int i;
72352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
73352f7f91STakashi Iwai 			kfree(kctl[i].name);
74352f7f91STakashi Iwai 	}
75352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
76352f7f91STakashi Iwai }
77352f7f91STakashi Iwai 
78352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
79352f7f91STakashi Iwai {
801da177e4SLinus Torvalds 	if (!spec)
811da177e4SLinus Torvalds 		return;
82352f7f91STakashi Iwai 	free_kctls(spec);
83352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
841da177e4SLinus Torvalds }
85352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds /*
881c70a583STakashi Iwai  * store user hints
891c70a583STakashi Iwai  */
901c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
911c70a583STakashi Iwai {
921c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
931c70a583STakashi Iwai 	int val;
941c70a583STakashi Iwai 
951c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
961c70a583STakashi Iwai 	if (val >= 0)
971c70a583STakashi Iwai 		codec->no_jack_detect = !val;
981c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
991c70a583STakashi Iwai 	if (val >= 0)
1001c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1011c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1021c70a583STakashi Iwai 	if (val >= 0)
1031c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1041c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1051c70a583STakashi Iwai 	if (val >= 0)
1061c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1071c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1081c70a583STakashi Iwai 	if (val >= 0)
1091c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1101c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1111c70a583STakashi Iwai 	if (val >= 0)
1121c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1131c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1141c70a583STakashi Iwai 	if (val >= 0)
1151c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
1221c70a583STakashi Iwai 
123f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
124f72706beSTakashi Iwai 	if (val >= 0)
125f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1261c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1271c70a583STakashi Iwai 	if (val >= 0)
1281c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1291c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1301c70a583STakashi Iwai 	if (val >= 0)
1311c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1321c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1331c70a583STakashi Iwai 	if (val >= 0)
1341c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1351c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1361c70a583STakashi Iwai 	if (val >= 0)
1371c70a583STakashi Iwai 		spec->no_primary_hp = !val;
1381c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1391c70a583STakashi Iwai 	if (val >= 0)
1401c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1411c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1421c70a583STakashi Iwai 	if (val >= 0)
1431c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1441c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1451c70a583STakashi Iwai 	if (val >= 0)
1461c70a583STakashi Iwai 		spec->indep_hp = !!val;
1471c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1481c70a583STakashi Iwai 	if (val >= 0)
1491c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->add_out_jack_modes = !!val;
15329476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
15429476558STakashi Iwai 	if (val >= 0)
15529476558STakashi Iwai 		spec->add_in_jack_modes = !!val;
1561c70a583STakashi Iwai 
1571c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1581c70a583STakashi Iwai 		spec->mixer_nid = val;
1591c70a583STakashi Iwai }
1601c70a583STakashi Iwai 
1611c70a583STakashi Iwai /*
1622c12c30dSTakashi Iwai  * pin control value accesses
1632c12c30dSTakashi Iwai  */
1642c12c30dSTakashi Iwai 
1652c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
1662c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
1672c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
1682c12c30dSTakashi Iwai 
1692c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
1702c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
1712c12c30dSTakashi Iwai {
1722c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
1732c12c30dSTakashi Iwai }
1742c12c30dSTakashi Iwai 
1752c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
1762c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
1772c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
1782c12c30dSTakashi Iwai {
1792c12c30dSTakashi Iwai 	if (!pin)
1802c12c30dSTakashi Iwai 		return;
1812c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
1822c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
1832c12c30dSTakashi Iwai 	if (do_write)
1842c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
1852c12c30dSTakashi Iwai }
1862c12c30dSTakashi Iwai 
1872c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
1882c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
1892c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
1902c12c30dSTakashi Iwai {
1912c12c30dSTakashi Iwai 	int i;
1922c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
1932c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
1942c12c30dSTakashi Iwai }
1952c12c30dSTakashi Iwai 
1962c12c30dSTakashi Iwai /*
197352f7f91STakashi Iwai  * parsing paths
1981da177e4SLinus Torvalds  */
1991da177e4SLinus Torvalds 
2003ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2013ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2023ca529d3STakashi Iwai {
2033ca529d3STakashi Iwai 	int i;
2043ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2053ca529d3STakashi Iwai 		if (list[i] == nid)
2063ca529d3STakashi Iwai 			return i;
2073ca529d3STakashi Iwai 	return -1;
2083ca529d3STakashi Iwai }
2093ca529d3STakashi Iwai 
2103ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2113ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2123ca529d3STakashi Iwai {
2133ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2143ca529d3STakashi Iwai }
2153ca529d3STakashi Iwai 
216f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
217f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2183ca529d3STakashi Iwai 				     int anchor_nid)
2191da177e4SLinus Torvalds {
220352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
221352f7f91STakashi Iwai 	int i;
2221da177e4SLinus Torvalds 
223352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
224352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
225352f7f91STakashi Iwai 		if (path->depth <= 0)
226352f7f91STakashi Iwai 			continue;
227352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
228f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2293ca529d3STakashi Iwai 			if (!anchor_nid ||
2303ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2313ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
232352f7f91STakashi Iwai 				return path;
2331da177e4SLinus Torvalds 		}
234f5172a7eSTakashi Iwai 	}
2351da177e4SLinus Torvalds 	return NULL;
2361da177e4SLinus Torvalds }
237f5172a7eSTakashi Iwai 
238f5172a7eSTakashi Iwai /* get the path between the given NIDs;
239f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
240f5172a7eSTakashi Iwai  */
241f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
242f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
243f5172a7eSTakashi Iwai {
2443ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
245f5172a7eSTakashi Iwai }
246352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
2471da177e4SLinus Torvalds 
248196c1766STakashi Iwai /* get the index number corresponding to the path instance;
249196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
250196c1766STakashi Iwai  */
251196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
252196c1766STakashi Iwai {
253196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
254196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
255196c1766STakashi Iwai 	ssize_t idx;
256196c1766STakashi Iwai 
257196c1766STakashi Iwai 	if (!spec->paths.used)
258196c1766STakashi Iwai 		return 0;
259196c1766STakashi Iwai 	idx = path - array;
260196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
261196c1766STakashi Iwai 		return 0;
262196c1766STakashi Iwai 	return idx + 1;
263196c1766STakashi Iwai }
264196c1766STakashi Iwai 
265196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
266196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
267196c1766STakashi Iwai {
268196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
269196c1766STakashi Iwai 
270196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
271196c1766STakashi Iwai 		return NULL;
272196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
273196c1766STakashi Iwai }
274196c1766STakashi Iwai 
275352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
276352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
2771da177e4SLinus Torvalds {
278352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
279352f7f91STakashi Iwai 	int i;
280352f7f91STakashi Iwai 
281352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
282352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
283352f7f91STakashi Iwai 		if (path->path[0] == nid)
284352f7f91STakashi Iwai 			return true;
285352f7f91STakashi Iwai 	}
286352f7f91STakashi Iwai 	return false;
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
289352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
290352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
291352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
2921da177e4SLinus Torvalds {
293352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
294352f7f91STakashi Iwai 		return false;
295352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298352f7f91STakashi Iwai /* nid, dir and idx */
299352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
300352f7f91STakashi Iwai 
301352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
302352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3031da177e4SLinus Torvalds {
304352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
305352f7f91STakashi Iwai 	int i;
306352f7f91STakashi Iwai 
307352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
308352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
309352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
310352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
311352f7f91STakashi Iwai 			return true;
312352f7f91STakashi Iwai 	}
313352f7f91STakashi Iwai 	return false;
3141da177e4SLinus Torvalds }
3151da177e4SLinus Torvalds 
316352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
317352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
318cb53c626STakashi Iwai 			      int dir, int idx)
319cb53c626STakashi Iwai {
320352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
321352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
322352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
323cb53c626STakashi Iwai }
324352f7f91STakashi Iwai 
3250c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
3260c8c0f56STakashi Iwai {
3270c8c0f56STakashi Iwai 	char buf[40];
3280c8c0f56STakashi Iwai 	int i;
3290c8c0f56STakashi Iwai 
3300c8c0f56STakashi Iwai 
3310c8c0f56STakashi Iwai 	buf[0] = 0;
3320c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
3330c8c0f56STakashi Iwai 		char tmp[4];
3340c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
3350c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
3360c8c0f56STakashi Iwai 	}
3370c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
3380c8c0f56STakashi Iwai }
3390c8c0f56STakashi Iwai 
340352f7f91STakashi Iwai /* called recursively */
341352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
342352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3433ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3443ca529d3STakashi Iwai 			     int depth)
345352f7f91STakashi Iwai {
346ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
347352f7f91STakashi Iwai 	int i, nums;
348352f7f91STakashi Iwai 
3493ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3503ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3513ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3523ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
353352f7f91STakashi Iwai 
354ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
355352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
356352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
357352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
358352f7f91STakashi Iwai 			 * try to find an empty DAC
359352f7f91STakashi Iwai 			 */
360352f7f91STakashi Iwai 			if (from_nid ||
361352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
362352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
363352f7f91STakashi Iwai 				continue;
364352f7f91STakashi Iwai 		}
3653ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
3663ca529d3STakashi Iwai 		if (anchor_nid <= 0)
367352f7f91STakashi Iwai 			goto found;
368352f7f91STakashi Iwai 	}
369352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
370352f7f91STakashi Iwai 		return false;
371352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
372352f7f91STakashi Iwai 		unsigned int type;
373352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
374352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
375352f7f91STakashi Iwai 		    type == AC_WID_PIN)
376352f7f91STakashi Iwai 			continue;
377352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
3783ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
379352f7f91STakashi Iwai 			goto found;
380352f7f91STakashi Iwai 	}
381352f7f91STakashi Iwai 	return false;
382352f7f91STakashi Iwai 
383352f7f91STakashi Iwai  found:
384352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
385352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
386352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
387352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
388352f7f91STakashi Iwai 	path->depth++;
389352f7f91STakashi Iwai 	return true;
390352f7f91STakashi Iwai }
391352f7f91STakashi Iwai 
392352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
393352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
3943ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
3953ca529d3STakashi Iwai  * with the given value are evaluated.
3963ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
3973ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
3983ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
399352f7f91STakashi Iwai  */
400352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4013ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
402352f7f91STakashi Iwai 			    struct nid_path *path)
403352f7f91STakashi Iwai {
4043ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
405352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
406352f7f91STakashi Iwai 		path->depth++;
407352f7f91STakashi Iwai 		return true;
408352f7f91STakashi Iwai 	}
409352f7f91STakashi Iwai 	return false;
410352f7f91STakashi Iwai }
411352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
412352f7f91STakashi Iwai 
413352f7f91STakashi Iwai /*
414352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
415352f7f91STakashi Iwai  * if no valid path is found, return NULL
416352f7f91STakashi Iwai  */
417352f7f91STakashi Iwai struct nid_path *
418352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4193ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
420352f7f91STakashi Iwai {
421352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
422352f7f91STakashi Iwai 	struct nid_path *path;
423352f7f91STakashi Iwai 
424352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
425352f7f91STakashi Iwai 		return NULL;
426352f7f91STakashi Iwai 
427f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4283ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
429f5172a7eSTakashi Iwai 	if (path)
430f5172a7eSTakashi Iwai 		return path;
431f5172a7eSTakashi Iwai 
432352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
433352f7f91STakashi Iwai 	if (!path)
434352f7f91STakashi Iwai 		return NULL;
435352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4363ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
437352f7f91STakashi Iwai 		return path;
438352f7f91STakashi Iwai 	/* push back */
439352f7f91STakashi Iwai 	spec->paths.used--;
440352f7f91STakashi Iwai 	return NULL;
441352f7f91STakashi Iwai }
442352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
443352f7f91STakashi Iwai 
444980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
445980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
446980428ceSTakashi Iwai {
447980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
448980428ceSTakashi Iwai 	if (!path)
449980428ceSTakashi Iwai 		return;
450980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
451980428ceSTakashi Iwai }
452980428ceSTakashi Iwai 
453352f7f91STakashi Iwai /* look for an empty DAC slot */
454352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
455352f7f91STakashi Iwai 			      bool is_digital)
456352f7f91STakashi Iwai {
457352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
458352f7f91STakashi Iwai 	bool cap_digital;
459352f7f91STakashi Iwai 	int i;
460352f7f91STakashi Iwai 
461352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
462352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
463352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
464352f7f91STakashi Iwai 			continue;
465352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
466352f7f91STakashi Iwai 		if (is_digital != cap_digital)
467352f7f91STakashi Iwai 			continue;
468352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
469352f7f91STakashi Iwai 			return nid;
470352f7f91STakashi Iwai 	}
471352f7f91STakashi Iwai 	return 0;
472352f7f91STakashi Iwai }
473352f7f91STakashi Iwai 
474352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
475352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
476352f7f91STakashi Iwai {
477352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
478352f7f91STakashi Iwai 	val |= chs << 16;
479352f7f91STakashi Iwai 	return val;
480352f7f91STakashi Iwai }
481352f7f91STakashi Iwai 
482352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
483352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
484352f7f91STakashi Iwai 			   int dir, unsigned int bits)
485352f7f91STakashi Iwai {
486352f7f91STakashi Iwai 	if (!nid)
487352f7f91STakashi Iwai 		return false;
488352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
489352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
490352f7f91STakashi Iwai 			return true;
491352f7f91STakashi Iwai 	return false;
492352f7f91STakashi Iwai }
493352f7f91STakashi Iwai 
49499a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
49599a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
49699a5592dSDavid Henningsson {
49799a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
49899a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
49999a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
50099a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
50199a5592dSDavid Henningsson }
50299a5592dSDavid Henningsson 
503352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
504352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
505352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
506352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
507352f7f91STakashi Iwai 
508352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
509352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
510352f7f91STakashi Iwai 				       struct nid_path *path)
511352f7f91STakashi Iwai {
512352f7f91STakashi Iwai 	int i;
513352f7f91STakashi Iwai 
514352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
515352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
516352f7f91STakashi Iwai 			return path->path[i];
517352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
518352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
519352f7f91STakashi Iwai 			return path->path[i];
520352f7f91STakashi Iwai 	}
521352f7f91STakashi Iwai 	return 0;
522352f7f91STakashi Iwai }
523352f7f91STakashi Iwai 
524352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
525352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
526352f7f91STakashi Iwai 				      struct nid_path *path)
527352f7f91STakashi Iwai {
528352f7f91STakashi Iwai 	int i;
529352f7f91STakashi Iwai 
530352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
531352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
532352f7f91STakashi Iwai 			return path->path[i];
533352f7f91STakashi Iwai 	}
534352f7f91STakashi Iwai 	return 0;
535352f7f91STakashi Iwai }
536352f7f91STakashi Iwai 
537352f7f91STakashi Iwai /*
538352f7f91STakashi Iwai  * path activation / deactivation
539352f7f91STakashi Iwai  */
540352f7f91STakashi Iwai 
541352f7f91STakashi Iwai /* can have the amp-in capability? */
542352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
543352f7f91STakashi Iwai {
544352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
545352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
546352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
547352f7f91STakashi Iwai 
548352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
549352f7f91STakashi Iwai 		return false;
550352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
551352f7f91STakashi Iwai 		return false;
552352f7f91STakashi Iwai 	return true;
553352f7f91STakashi Iwai }
554352f7f91STakashi Iwai 
555352f7f91STakashi Iwai /* can have the amp-out capability? */
556352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
557352f7f91STakashi Iwai {
558352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
559352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
560352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
561352f7f91STakashi Iwai 
562352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
563352f7f91STakashi Iwai 		return false;
564352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
565352f7f91STakashi Iwai 		return false;
566352f7f91STakashi Iwai 	return true;
567352f7f91STakashi Iwai }
568352f7f91STakashi Iwai 
569352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
570352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
571352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
572352f7f91STakashi Iwai {
573352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
574352f7f91STakashi Iwai 	int i, n;
575352f7f91STakashi Iwai 
576352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
577352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
578352f7f91STakashi Iwai 		if (!path->active)
579352f7f91STakashi Iwai 			continue;
580352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
581352f7f91STakashi Iwai 			if (path->path[i] == nid) {
582352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
583352f7f91STakashi Iwai 					return true;
584352f7f91STakashi Iwai 				break;
585352f7f91STakashi Iwai 			}
586352f7f91STakashi Iwai 		}
587352f7f91STakashi Iwai 	}
588352f7f91STakashi Iwai 	return false;
589352f7f91STakashi Iwai }
590352f7f91STakashi Iwai 
591352f7f91STakashi Iwai /* get the default amp value for the target state */
592352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
593352f7f91STakashi Iwai 				   int dir, bool enable)
594352f7f91STakashi Iwai {
595352f7f91STakashi Iwai 	unsigned int caps;
596352f7f91STakashi Iwai 	unsigned int val = 0;
597352f7f91STakashi Iwai 
598352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
599352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
600352f7f91STakashi Iwai 		/* set to 0dB */
601352f7f91STakashi Iwai 		if (enable)
602352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
603352f7f91STakashi Iwai 	}
604352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
605352f7f91STakashi Iwai 		if (!enable)
606352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
607352f7f91STakashi Iwai 	}
608352f7f91STakashi Iwai 	return val;
609352f7f91STakashi Iwai }
610352f7f91STakashi Iwai 
611352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
612352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
613352f7f91STakashi Iwai {
614352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
615352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
616352f7f91STakashi Iwai }
617352f7f91STakashi Iwai 
618352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
619352f7f91STakashi Iwai 			 int idx, bool enable)
620352f7f91STakashi Iwai {
621352f7f91STakashi Iwai 	int val;
622352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
623985803caSTakashi Iwai 	    (!enable && is_active_nid(codec, nid, dir, idx)))
624352f7f91STakashi Iwai 		return;
625352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
626352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
627352f7f91STakashi Iwai }
628352f7f91STakashi Iwai 
629352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
630352f7f91STakashi Iwai 			     int i, bool enable)
631352f7f91STakashi Iwai {
632352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
633352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
634352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
635352f7f91STakashi Iwai }
636352f7f91STakashi Iwai 
637352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
638352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
639352f7f91STakashi Iwai {
640352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
641ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
642352f7f91STakashi Iwai 	int n, nums, idx;
643352f7f91STakashi Iwai 	int type;
644352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
645352f7f91STakashi Iwai 
646ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
647352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
648352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
649352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
650352f7f91STakashi Iwai 		nums = 1;
651352f7f91STakashi Iwai 		idx = 0;
652352f7f91STakashi Iwai 	} else
653352f7f91STakashi Iwai 		idx = path->idx[i];
654352f7f91STakashi Iwai 
655352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
656352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
657352f7f91STakashi Iwai 
658352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
659352f7f91STakashi Iwai 		return;
660352f7f91STakashi Iwai 
661352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
662352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
663352f7f91STakashi Iwai 	 */
664352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
665352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
666352f7f91STakashi Iwai 			continue;
667352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
668352f7f91STakashi Iwai 	}
669352f7f91STakashi Iwai }
670352f7f91STakashi Iwai 
671352f7f91STakashi Iwai /* activate or deactivate the given path
672352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
673352f7f91STakashi Iwai  */
674352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
675352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
676352f7f91STakashi Iwai {
677352f7f91STakashi Iwai 	int i;
678352f7f91STakashi Iwai 
679352f7f91STakashi Iwai 	if (!enable)
680352f7f91STakashi Iwai 		path->active = false;
681352f7f91STakashi Iwai 
682352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
683352f7f91STakashi Iwai 		if (enable && path->multi[i])
684352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
685352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
686352f7f91STakashi Iwai 					    path->idx[i]);
687352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
688352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
689352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
690352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
691352f7f91STakashi Iwai 	}
692352f7f91STakashi Iwai 
693352f7f91STakashi Iwai 	if (enable)
694352f7f91STakashi Iwai 		path->active = true;
695352f7f91STakashi Iwai }
696352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
697352f7f91STakashi Iwai 
698d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
699d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
700d5a9f1bbSTakashi Iwai {
701d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
702d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
703d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
704d5a9f1bbSTakashi Iwai 		return;
705ecac3ed1STakashi Iwai 	if (codec->inv_eapd)
706ecac3ed1STakashi Iwai 		enable = !enable;
707d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
708d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
709d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
710d5a9f1bbSTakashi Iwai }
711d5a9f1bbSTakashi Iwai 
712352f7f91STakashi Iwai 
713352f7f91STakashi Iwai /*
714352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
715352f7f91STakashi Iwai  */
716352f7f91STakashi Iwai 
717352f7f91STakashi Iwai enum {
718352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
719352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
720352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
721352f7f91STakashi Iwai };
722352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
723352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
724352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
725352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
726352f7f91STakashi Iwai };
727352f7f91STakashi Iwai 
728352f7f91STakashi Iwai /* add dynamic controls from template */
729352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
730352f7f91STakashi Iwai 		       int cidx, unsigned long val)
731352f7f91STakashi Iwai {
732352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
733352f7f91STakashi Iwai 
73412c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
735352f7f91STakashi Iwai 	if (!knew)
736352f7f91STakashi Iwai 		return -ENOMEM;
737352f7f91STakashi Iwai 	knew->index = cidx;
738352f7f91STakashi Iwai 	if (get_amp_nid_(val))
739352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
740352f7f91STakashi Iwai 	knew->private_value = val;
741352f7f91STakashi Iwai 	return 0;
742352f7f91STakashi Iwai }
743352f7f91STakashi Iwai 
744352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
745352f7f91STakashi Iwai 				const char *pfx, const char *dir,
746352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
747352f7f91STakashi Iwai {
748352f7f91STakashi Iwai 	char name[32];
749352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
750352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
751352f7f91STakashi Iwai }
752352f7f91STakashi Iwai 
753352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
754352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
755352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
756352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
757352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
758352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
759352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
760352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
761352f7f91STakashi Iwai 
762352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
763352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
764352f7f91STakashi Iwai {
765352f7f91STakashi Iwai 	unsigned int val;
766352f7f91STakashi Iwai 	if (!path)
767352f7f91STakashi Iwai 		return 0;
768352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
769352f7f91STakashi Iwai 	if (!val)
770352f7f91STakashi Iwai 		return 0;
771352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
772352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
773352f7f91STakashi Iwai }
774352f7f91STakashi Iwai 
775352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
776352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
777352f7f91STakashi Iwai 			       int type)
778352f7f91STakashi Iwai {
779352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
780352f7f91STakashi Iwai 	if (path) {
781352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
782352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
783352f7f91STakashi Iwai 			chs = 3; /* stereo */
784352f7f91STakashi Iwai 	}
785352f7f91STakashi Iwai 	return chs;
786352f7f91STakashi Iwai }
787352f7f91STakashi Iwai 
788352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
789352f7f91STakashi Iwai 			  struct nid_path *path)
790352f7f91STakashi Iwai {
791352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
792352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
793352f7f91STakashi Iwai }
794352f7f91STakashi Iwai 
795352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
796352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
797352f7f91STakashi Iwai  */
798352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
799352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
800352f7f91STakashi Iwai {
801352f7f91STakashi Iwai 	unsigned int val;
802352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
803352f7f91STakashi Iwai 
804352f7f91STakashi Iwai 	if (!path)
805352f7f91STakashi Iwai 		return 0;
806352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
807352f7f91STakashi Iwai 	if (!val)
808352f7f91STakashi Iwai 		return 0;
809352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
810352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
811352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
812352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
813352f7f91STakashi Iwai 		if (nums > 1) {
814352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
815352f7f91STakashi Iwai 			val |= nums << 19;
816352f7f91STakashi Iwai 		}
817352f7f91STakashi Iwai 	}
818352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
819352f7f91STakashi Iwai }
820352f7f91STakashi Iwai 
821352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
822352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
823352f7f91STakashi Iwai {
824352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
825352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
826352f7f91STakashi Iwai }
827352f7f91STakashi Iwai 
828247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
829247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
830247d85eeSTakashi Iwai {
831247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
832247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
833247d85eeSTakashi Iwai }
834247d85eeSTakashi Iwai 
835352f7f91STakashi Iwai static const char * const channel_name[4] = {
836352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
837352f7f91STakashi Iwai };
838352f7f91STakashi Iwai 
839352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
840247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
841247d85eeSTakashi Iwai 				    int *index, int ctl_type)
842352f7f91STakashi Iwai {
843247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
844352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
845352f7f91STakashi Iwai 
846352f7f91STakashi Iwai 	*index = 0;
847352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
848247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
849352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
850352f7f91STakashi Iwai 
851352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
852352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
853352f7f91STakashi Iwai 	 */
854352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
855352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
856352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
857352f7f91STakashi Iwai 
858247d85eeSTakashi Iwai 	/* multi-io channels */
859247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
860247d85eeSTakashi Iwai 		return channel_name[ch];
861247d85eeSTakashi Iwai 
862352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
863352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
864247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
865247d85eeSTakashi Iwai 		 * don't name it as Speaker
866247d85eeSTakashi Iwai 		 */
867247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
868247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
869247d85eeSTakashi Iwai 			break;
870352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
871352f7f91STakashi Iwai 			return "Speaker";
872352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
873352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
874352f7f91STakashi Iwai 		break;
875352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
876247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
877247d85eeSTakashi Iwai 		 * don't name it as Headphone
878247d85eeSTakashi Iwai 		 */
879247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
880247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
881247d85eeSTakashi Iwai 			break;
882352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
883352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
884352f7f91STakashi Iwai 			break;
885352f7f91STakashi Iwai 		*index = ch;
886352f7f91STakashi Iwai 		return "Headphone";
887247d85eeSTakashi Iwai 	}
888247d85eeSTakashi Iwai 
889247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
890352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
891352f7f91STakashi Iwai 		return "PCM";
892247d85eeSTakashi Iwai 
893352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
894352f7f91STakashi Iwai 		snd_BUG();
895352f7f91STakashi Iwai 		return "PCM";
896352f7f91STakashi Iwai 	}
897352f7f91STakashi Iwai 
898352f7f91STakashi Iwai 	return channel_name[ch];
899352f7f91STakashi Iwai }
900352f7f91STakashi Iwai 
901352f7f91STakashi Iwai /*
902352f7f91STakashi Iwai  * Parse output paths
903352f7f91STakashi Iwai  */
904352f7f91STakashi Iwai 
905352f7f91STakashi Iwai /* badness definition */
906352f7f91STakashi Iwai enum {
907352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
908352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
909352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
910352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
911352f7f91STakashi Iwai 	/* No possible multi-ios */
912352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
913352f7f91STakashi Iwai 	/* No individual DAC for extra output */
914352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
915352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
916352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
917352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
918352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
919352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
920352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
921352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
922352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
923352f7f91STakashi Iwai 	/* Volume widget is shared */
924352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
925352f7f91STakashi Iwai };
926352f7f91STakashi Iwai 
9270e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
928352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
929352f7f91STakashi Iwai  *
930352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
931352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
932352f7f91STakashi Iwai  * total badness for both volume and mute controls.
933352f7f91STakashi Iwai  */
9340e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
935352f7f91STakashi Iwai {
936352f7f91STakashi Iwai 	hda_nid_t nid;
937352f7f91STakashi Iwai 	unsigned int val;
938352f7f91STakashi Iwai 	int badness = 0;
939352f7f91STakashi Iwai 
940352f7f91STakashi Iwai 	if (!path)
941352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
9420e614dd0STakashi Iwai 
9430e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
9440e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
9450e614dd0STakashi Iwai 		return 0; /* already evaluated */
9460e614dd0STakashi Iwai 
947352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
948352f7f91STakashi Iwai 	if (nid) {
949352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
950352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
951352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
952352f7f91STakashi Iwai 		else
953352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
954352f7f91STakashi Iwai 	} else
955352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
956352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
957352f7f91STakashi Iwai 	if (nid) {
958352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
959352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
960352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
961352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
962352f7f91STakashi Iwai 		else
963352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
964352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
965352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
966352f7f91STakashi Iwai 		else
967352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
968352f7f91STakashi Iwai 	} else
969352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
970352f7f91STakashi Iwai 	return badness;
971352f7f91STakashi Iwai }
972352f7f91STakashi Iwai 
973352f7f91STakashi Iwai struct badness_table {
974352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
975352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
976352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
977352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
978352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
979352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
980352f7f91STakashi Iwai };
981352f7f91STakashi Iwai 
982352f7f91STakashi Iwai static struct badness_table main_out_badness = {
983352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
984352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
985352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
986352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
987352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
988352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
989352f7f91STakashi Iwai };
990352f7f91STakashi Iwai 
991352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
992352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
993352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
994352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
995352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
996352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
997352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
998352f7f91STakashi Iwai };
999352f7f91STakashi Iwai 
10007385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
10017385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
10027385df61STakashi Iwai {
10037385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10047385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
10057385df61STakashi Iwai 
10067385df61STakashi Iwai 	if (cfg->line_outs > idx)
10077385df61STakashi Iwai 		return spec->private_dac_nids[idx];
10087385df61STakashi Iwai 	idx -= cfg->line_outs;
10097385df61STakashi Iwai 	if (spec->multi_ios > idx)
10107385df61STakashi Iwai 		return spec->multi_io[idx].dac;
10117385df61STakashi Iwai 	return 0;
10127385df61STakashi Iwai }
10137385df61STakashi Iwai 
10147385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
10157385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
10167385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
10177385df61STakashi Iwai {
10187385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
10197385df61STakashi Iwai }
10207385df61STakashi Iwai 
1021352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1022352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1023352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1024196c1766STakashi Iwai 			   int *path_idx,
1025352f7f91STakashi Iwai 			   const struct badness_table *bad)
1026352f7f91STakashi Iwai {
1027352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1028352f7f91STakashi Iwai 	int i, j;
1029352f7f91STakashi Iwai 	int badness = 0;
1030352f7f91STakashi Iwai 	hda_nid_t dac;
1031352f7f91STakashi Iwai 
1032352f7f91STakashi Iwai 	if (!num_outs)
1033352f7f91STakashi Iwai 		return 0;
1034352f7f91STakashi Iwai 
1035352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
10360c8c0f56STakashi Iwai 		struct nid_path *path;
1037352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
10381e0b5286STakashi Iwai 
10390e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
10400e614dd0STakashi Iwai 		if (path) {
10410e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
10421e0b5286STakashi Iwai 			continue;
10431e0b5286STakashi Iwai 		}
10441e0b5286STakashi Iwai 
1045352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1046352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1047980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1048352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1049352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1050352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1051352f7f91STakashi Iwai 					dacs[j] = 0;
1052980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1053196c1766STakashi Iwai 					path_idx[j] = 0;
1054352f7f91STakashi Iwai 					break;
1055352f7f91STakashi Iwai 				}
1056352f7f91STakashi Iwai 			}
1057352f7f91STakashi Iwai 		}
1058352f7f91STakashi Iwai 		dac = dacs[i];
1059352f7f91STakashi Iwai 		if (!dac) {
10607385df61STakashi Iwai 			if (num_outs > 2)
10617385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
10627385df61STakashi Iwai 			if (!dac)
10637385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
10647385df61STakashi Iwai 			if (!dac)
10657385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1066352f7f91STakashi Iwai 			if (dac) {
1067352f7f91STakashi Iwai 				if (!i)
1068352f7f91STakashi Iwai 					badness += bad->shared_primary;
1069352f7f91STakashi Iwai 				else if (i == 1)
1070352f7f91STakashi Iwai 					badness += bad->shared_surr;
1071352f7f91STakashi Iwai 				else
1072352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1073352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1074352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1075352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1076352f7f91STakashi Iwai 			} else if (!i)
1077352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1078352f7f91STakashi Iwai 			else
1079352f7f91STakashi Iwai 				badness += bad->no_dac;
1080352f7f91STakashi Iwai 		}
10813ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1082117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1083b3a8c745STakashi Iwai 			/* try with aamix */
10843ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1085b3a8c745STakashi Iwai 		}
10860c8c0f56STakashi Iwai 		if (!path)
1087352f7f91STakashi Iwai 			dac = dacs[i] = 0;
1088e1284af7STakashi Iwai 		else {
10890c8c0f56STakashi Iwai 			print_nid_path("output", path);
1090e1284af7STakashi Iwai 			path->active = true;
1091196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
10920e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1093e1284af7STakashi Iwai 		}
1094352f7f91STakashi Iwai 	}
1095352f7f91STakashi Iwai 
1096352f7f91STakashi Iwai 	return badness;
1097352f7f91STakashi Iwai }
1098352f7f91STakashi Iwai 
1099352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1100352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1101352f7f91STakashi Iwai {
1102352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1103352f7f91STakashi Iwai 	int i;
1104352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1105352f7f91STakashi Iwai 
1106352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1107352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1108352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1109352f7f91STakashi Iwai 			continue;
1110352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1111352f7f91STakashi Iwai 			if (nid_found)
1112352f7f91STakashi Iwai 				return 0;
1113352f7f91STakashi Iwai 			nid_found = nid;
1114352f7f91STakashi Iwai 		}
1115352f7f91STakashi Iwai 	}
1116352f7f91STakashi Iwai 	return nid_found;
1117352f7f91STakashi Iwai }
1118352f7f91STakashi Iwai 
1119352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1120352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1121352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1122352f7f91STakashi Iwai {
1123352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1124352f7f91STakashi Iwai 
1125352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1126352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1127352f7f91STakashi Iwai 		return false;
1128352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1129352f7f91STakashi Iwai 		return false;
1130352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1131352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1132352f7f91STakashi Iwai 		return false;
1133352f7f91STakashi Iwai 	return true;
1134352f7f91STakashi Iwai }
1135352f7f91STakashi Iwai 
1136e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1137e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1138e22aab7dSTakashi Iwai {
1139e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1140e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1141e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1142e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1143e22aab7dSTakashi Iwai 	int type, i;
1144e22aab7dSTakashi Iwai 	int num_pins = 0;
1145e22aab7dSTakashi Iwai 
1146e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1147e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1148e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1149e22aab7dSTakashi Iwai 				continue;
1150e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1151e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1152e22aab7dSTakashi Iwai 				num_pins++;
1153e22aab7dSTakashi Iwai 		}
1154e22aab7dSTakashi Iwai 	}
1155e22aab7dSTakashi Iwai 	return num_pins;
1156e22aab7dSTakashi Iwai }
1157e22aab7dSTakashi Iwai 
1158352f7f91STakashi Iwai /*
1159352f7f91STakashi Iwai  * multi-io helper
1160352f7f91STakashi Iwai  *
1161352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1162352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1163352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1164352f7f91STakashi Iwai  * the badness value.
1165352f7f91STakashi Iwai  */
1166352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1167352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1168e22aab7dSTakashi Iwai 			  bool hardwired)
1169352f7f91STakashi Iwai {
1170352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1171352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1172e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1173352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1174352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1175352f7f91STakashi Iwai 	int badness = 0;
11760e614dd0STakashi Iwai 	struct nid_path *path;
1177352f7f91STakashi Iwai 
1178352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1179352f7f91STakashi Iwai 	if (old_pins >= 2)
1180352f7f91STakashi Iwai 		goto end_fill;
1181352f7f91STakashi Iwai 
1182e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1183352f7f91STakashi Iwai 	if (num_pins < 2)
1184352f7f91STakashi Iwai 		goto end_fill;
1185352f7f91STakashi Iwai 
1186352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1187352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1188352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1189352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1190352f7f91STakashi Iwai 
1191352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1192352f7f91STakashi Iwai 				continue;
1193352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1194352f7f91STakashi Iwai 				continue;
1195352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1196352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1197352f7f91STakashi Iwai 					break;
1198352f7f91STakashi Iwai 			}
1199352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1200352f7f91STakashi Iwai 				continue;
1201352f7f91STakashi Iwai 
1202352f7f91STakashi Iwai 			if (hardwired)
1203352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1204352f7f91STakashi Iwai 			else if (!dac)
1205352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1206352f7f91STakashi Iwai 			if (!dac) {
1207352f7f91STakashi Iwai 				badness++;
1208352f7f91STakashi Iwai 				continue;
1209352f7f91STakashi Iwai 			}
12103ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
12113ca529d3STakashi Iwai 						    -spec->mixer_nid);
12120c8c0f56STakashi Iwai 			if (!path) {
1213352f7f91STakashi Iwai 				badness++;
1214352f7f91STakashi Iwai 				continue;
1215352f7f91STakashi Iwai 			}
12160c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1217352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1218352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1219196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1220196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1221352f7f91STakashi Iwai 			spec->multi_ios++;
1222352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1223352f7f91STakashi Iwai 				break;
1224352f7f91STakashi Iwai 		}
1225352f7f91STakashi Iwai 	}
1226352f7f91STakashi Iwai  end_fill:
1227352f7f91STakashi Iwai 	if (badness)
1228352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1229352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1230352f7f91STakashi Iwai 		if (hardwired)
1231352f7f91STakashi Iwai 			return 1; /* nothing found */
1232352f7f91STakashi Iwai 		else
1233352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1234352f7f91STakashi Iwai 	}
1235352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1236352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1237352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1238352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1239352f7f91STakashi Iwai 		return badness;
1240352f7f91STakashi Iwai 	}
1241352f7f91STakashi Iwai 
1242352f7f91STakashi Iwai 	/* assign volume and mute controls */
12430e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
12440e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
12450e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
12460e614dd0STakashi Iwai 	}
1247352f7f91STakashi Iwai 
1248352f7f91STakashi Iwai 	return badness;
1249352f7f91STakashi Iwai }
1250352f7f91STakashi Iwai 
1251352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1252352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1253196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1254352f7f91STakashi Iwai {
1255b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1256352f7f91STakashi Iwai 	int i;
1257352f7f91STakashi Iwai 	bool found = false;
1258352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
12590c8c0f56STakashi Iwai 		struct nid_path *path;
1260352f7f91STakashi Iwai 		hda_nid_t dac;
1261352f7f91STakashi Iwai 		if (dacs[i])
1262352f7f91STakashi Iwai 			continue;
1263352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1264352f7f91STakashi Iwai 		if (!dac)
1265352f7f91STakashi Iwai 			continue;
12663ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
12673ca529d3STakashi Iwai 					    -spec->mixer_nid);
1268117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
12693ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
12700c8c0f56STakashi Iwai 		if (path) {
1271352f7f91STakashi Iwai 			dacs[i] = dac;
1272352f7f91STakashi Iwai 			found = true;
12730c8c0f56STakashi Iwai 			print_nid_path("output", path);
1274e1284af7STakashi Iwai 			path->active = true;
1275196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1276352f7f91STakashi Iwai 		}
1277352f7f91STakashi Iwai 	}
1278352f7f91STakashi Iwai 	return found;
1279352f7f91STakashi Iwai }
1280352f7f91STakashi Iwai 
1281c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1282c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1283c30aa7b2STakashi Iwai {
12843ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1285c30aa7b2STakashi Iwai 	struct nid_path *path;
1286c30aa7b2STakashi Iwai 
1287c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
12883ca529d3STakashi Iwai 	if (!path || !path->depth ||
12893ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1290c30aa7b2STakashi Iwai 		return 0;
1291c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1292c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
12933ca529d3STakashi Iwai 				    spec->mixer_nid);
1294c30aa7b2STakashi Iwai 	if (!path)
1295c30aa7b2STakashi Iwai 		return 0;
1296c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1297c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1298c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1299c30aa7b2STakashi Iwai }
1300c30aa7b2STakashi Iwai 
1301a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1302a07a949bSTakashi Iwai  * shared dac pointed by the paths
1303a07a949bSTakashi Iwai  */
1304a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1305a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1306a07a949bSTakashi Iwai {
1307a07a949bSTakashi Iwai 	struct nid_path *path;
1308a07a949bSTakashi Iwai 	int i;
1309a07a949bSTakashi Iwai 
1310a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1311a07a949bSTakashi Iwai 		if (dacs[i])
1312a07a949bSTakashi Iwai 			continue;
1313a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1314a07a949bSTakashi Iwai 		if (!path)
1315a07a949bSTakashi Iwai 			continue;
1316a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1317a07a949bSTakashi Iwai 	}
1318a07a949bSTakashi Iwai }
1319a07a949bSTakashi Iwai 
1320352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1321352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1322352f7f91STakashi Iwai 			      bool fill_hardwired,
1323352f7f91STakashi Iwai 			      bool fill_mio_first)
1324352f7f91STakashi Iwai {
1325352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1326352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1327352f7f91STakashi Iwai 	int i, err, badness;
1328ea46c3c8STakashi Iwai 	unsigned int val;
1329352f7f91STakashi Iwai 
1330352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1331352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1332352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1333352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1334352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1335352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1336352f7f91STakashi Iwai 	spec->multi_ios = 0;
1337352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1338cd5be3f9STakashi Iwai 
1339cd5be3f9STakashi Iwai 	/* clear path indices */
1340cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1341cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1342cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1343cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1344cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1345c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1346cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1347cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1348cd5be3f9STakashi Iwai 
1349352f7f91STakashi Iwai 	badness = 0;
1350352f7f91STakashi Iwai 
1351352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1352352f7f91STakashi Iwai 	if (fill_hardwired) {
1353352f7f91STakashi Iwai 		bool mapped;
1354352f7f91STakashi Iwai 		do {
1355352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1356352f7f91STakashi Iwai 					     cfg->line_out_pins,
1357196c1766STakashi Iwai 					     spec->private_dac_nids,
1358196c1766STakashi Iwai 					     spec->out_paths);
1359352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1360352f7f91STakashi Iwai 					      cfg->hp_pins,
1361196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1362196c1766STakashi Iwai 					      spec->hp_paths);
1363352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1364352f7f91STakashi Iwai 					      cfg->speaker_pins,
1365196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1366196c1766STakashi Iwai 					      spec->speaker_paths);
1367352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1368352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1369e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1370352f7f91STakashi Iwai 				if (!err)
1371352f7f91STakashi Iwai 					mapped = true;
1372352f7f91STakashi Iwai 			}
1373352f7f91STakashi Iwai 		} while (mapped);
1374352f7f91STakashi Iwai 	}
1375352f7f91STakashi Iwai 
1376352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1377196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1378352f7f91STakashi Iwai 				   &main_out_badness);
1379352f7f91STakashi Iwai 
1380352f7f91STakashi Iwai 	if (fill_mio_first &&
1381352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1382352f7f91STakashi Iwai 		/* try to fill multi-io first */
1383e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1384352f7f91STakashi Iwai 		if (err < 0)
1385352f7f91STakashi Iwai 			return err;
1386352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1387352f7f91STakashi Iwai 	}
1388352f7f91STakashi Iwai 
1389352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1390352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1391352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1392196c1766STakashi Iwai 				      spec->hp_paths,
1393352f7f91STakashi Iwai 				      &extra_out_badness);
1394352f7f91STakashi Iwai 		if (err < 0)
1395352f7f91STakashi Iwai 			return err;
1396352f7f91STakashi Iwai 		badness += err;
1397352f7f91STakashi Iwai 	}
1398352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1399352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1400352f7f91STakashi Iwai 				      cfg->speaker_pins,
1401352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1402196c1766STakashi Iwai 				      spec->speaker_paths,
1403352f7f91STakashi Iwai 				      &extra_out_badness);
1404352f7f91STakashi Iwai 		if (err < 0)
1405352f7f91STakashi Iwai 			return err;
1406352f7f91STakashi Iwai 		badness += err;
1407352f7f91STakashi Iwai 	}
1408352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1409e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1410352f7f91STakashi Iwai 		if (err < 0)
1411352f7f91STakashi Iwai 			return err;
1412352f7f91STakashi Iwai 		badness += err;
1413352f7f91STakashi Iwai 	}
1414e22aab7dSTakashi Iwai 
1415c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1416c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1417c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1418c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1419c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1420c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1421c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1422c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1423c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1424c30aa7b2STakashi Iwai 	}
1425c30aa7b2STakashi Iwai 
1426e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1427e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1428e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1429352f7f91STakashi Iwai 
1430a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1431a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1432a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1433a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1434a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1435a07a949bSTakashi Iwai 		else {
1436a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1437a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1438a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1439a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1440a07a949bSTakashi Iwai 		}
1441a07a949bSTakashi Iwai 	}
1442a07a949bSTakashi Iwai 
1443a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1444c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1445a07a949bSTakashi Iwai 
1446352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1447352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1448352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1449352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1450352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1451352f7f91STakashi Iwai 		spec->multi_ios = 0;
1452352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1453352f7f91STakashi Iwai 	}
1454352f7f91STakashi Iwai 
1455a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1456a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1457a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1458a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1459a07a949bSTakashi Iwai 				   spec->hp_paths);
1460a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1461a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1462a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1463a07a949bSTakashi Iwai 				   spec->speaker_paths);
1464a07a949bSTakashi Iwai 
14652c12c30dSTakashi Iwai 	/* set initial pinctl targets */
1466ea46c3c8STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
1467ea46c3c8STakashi Iwai 		val = PIN_HP;
1468ea46c3c8STakashi Iwai 	else
1469ea46c3c8STakashi Iwai 		val = PIN_OUT;
1470ea46c3c8STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
14712c12c30dSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
14722c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
1473ea46c3c8STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1474ea46c3c8STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
14752c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
1476ea46c3c8STakashi Iwai 				cfg->speaker_pins, val);
1477ea46c3c8STakashi Iwai 	}
14782c12c30dSTakashi Iwai 
1479352f7f91STakashi Iwai 	return badness;
1480352f7f91STakashi Iwai }
1481352f7f91STakashi Iwai 
1482352f7f91STakashi Iwai #define DEBUG_BADNESS
1483352f7f91STakashi Iwai 
1484352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1485352f7f91STakashi Iwai #define debug_badness	snd_printdd
1486352f7f91STakashi Iwai #else
1487352f7f91STakashi Iwai #define debug_badness(...)
1488352f7f91STakashi Iwai #endif
1489352f7f91STakashi Iwai 
1490352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1491352f7f91STakashi Iwai {
1492352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1493352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1494708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1495352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1496352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1497352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1498352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1499352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1500352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1501352f7f91STakashi Iwai 			      spec->multi_ios,
1502352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1503352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1504352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1505352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1506708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1507352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1508352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1509352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1510352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1511352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1512352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1513352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1514352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1515352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1516352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1517352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1518352f7f91STakashi Iwai }
1519352f7f91STakashi Iwai 
1520352f7f91STakashi Iwai /* find all available DACs of the codec */
1521352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1522352f7f91STakashi Iwai {
1523352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1524352f7f91STakashi Iwai 	int i;
1525352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1526352f7f91STakashi Iwai 
1527352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1528352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1529352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1530352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1531352f7f91STakashi Iwai 			continue;
1532352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1533352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1534352f7f91STakashi Iwai 			break;
1535352f7f91STakashi Iwai 		}
1536352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1537352f7f91STakashi Iwai 	}
1538352f7f91STakashi Iwai }
1539352f7f91STakashi Iwai 
1540352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1541352f7f91STakashi Iwai {
1542352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1543352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1544352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1545352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1546352f7f91STakashi Iwai 	int badness;
1547352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1548352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1549352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1550352f7f91STakashi Iwai 
1551352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1552352f7f91STakashi Iwai 	if (!best_cfg)
1553352f7f91STakashi Iwai 		return -ENOMEM;
1554352f7f91STakashi Iwai 	*best_cfg = *cfg;
1555352f7f91STakashi Iwai 
1556352f7f91STakashi Iwai 	for (;;) {
1557352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1558352f7f91STakashi Iwai 					     fill_mio_first);
1559352f7f91STakashi Iwai 		if (badness < 0) {
1560352f7f91STakashi Iwai 			kfree(best_cfg);
1561352f7f91STakashi Iwai 			return badness;
1562352f7f91STakashi Iwai 		}
1563352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1564352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1565352f7f91STakashi Iwai 			      badness);
1566352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1567352f7f91STakashi Iwai 		if (badness < best_badness) {
1568352f7f91STakashi Iwai 			best_badness = badness;
1569352f7f91STakashi Iwai 			*best_cfg = *cfg;
1570352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1571352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1572352f7f91STakashi Iwai 		}
1573352f7f91STakashi Iwai 		if (!badness)
1574352f7f91STakashi Iwai 			break;
1575352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1576352f7f91STakashi Iwai 		if (!fill_mio_first)
1577352f7f91STakashi Iwai 			continue;
1578352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1579352f7f91STakashi Iwai 		if (!fill_hardwired)
1580352f7f91STakashi Iwai 			continue;
1581352f7f91STakashi Iwai 		if (hp_spk_swapped)
1582352f7f91STakashi Iwai 			break;
1583352f7f91STakashi Iwai 		hp_spk_swapped = true;
1584352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1585352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1586352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1587352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1588352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1589352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1590352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1591352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1592352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1593352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1594352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1595352f7f91STakashi Iwai 			fill_hardwired = true;
1596352f7f91STakashi Iwai 			continue;
1597352f7f91STakashi Iwai 		}
1598352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1599352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1600352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1601352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1602352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1603352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1604352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1605352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1606352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1607352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1608352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1609352f7f91STakashi Iwai 			fill_hardwired = true;
1610352f7f91STakashi Iwai 			continue;
1611352f7f91STakashi Iwai 		}
1612352f7f91STakashi Iwai 		break;
1613352f7f91STakashi Iwai 	}
1614352f7f91STakashi Iwai 
1615352f7f91STakashi Iwai 	if (badness) {
16160c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1617352f7f91STakashi Iwai 		*cfg = *best_cfg;
1618352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1619352f7f91STakashi Iwai 	}
1620352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1621352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1622352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1623352f7f91STakashi Iwai 
1624352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1625352f7f91STakashi Iwai 		struct nid_path *path;
1626196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1627352f7f91STakashi Iwai 		if (path)
1628352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
16297a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
16307a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
16317a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1632352f7f91STakashi Iwai 	}
1633352f7f91STakashi Iwai 
1634352f7f91STakashi Iwai 	kfree(best_cfg);
1635352f7f91STakashi Iwai 	return 0;
1636352f7f91STakashi Iwai }
1637352f7f91STakashi Iwai 
1638352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1639352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1640352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1641352f7f91STakashi Iwai {
1642352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1643352f7f91STakashi Iwai 	int i, err, noutputs;
1644352f7f91STakashi Iwai 
1645352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1646352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1647352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1648352f7f91STakashi Iwai 
1649352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1650352f7f91STakashi Iwai 		const char *name;
1651352f7f91STakashi Iwai 		int index;
1652352f7f91STakashi Iwai 		struct nid_path *path;
1653352f7f91STakashi Iwai 
1654196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1655352f7f91STakashi Iwai 		if (!path)
1656352f7f91STakashi Iwai 			continue;
1657247d85eeSTakashi Iwai 
1658247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1659352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1660352f7f91STakashi Iwai 			/* Center/LFE */
1661352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1662352f7f91STakashi Iwai 			if (err < 0)
1663352f7f91STakashi Iwai 				return err;
1664352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1665352f7f91STakashi Iwai 			if (err < 0)
1666352f7f91STakashi Iwai 				return err;
1667247d85eeSTakashi Iwai 		} else {
1668247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1669247d85eeSTakashi Iwai 			if (err < 0)
1670247d85eeSTakashi Iwai 				return err;
1671247d85eeSTakashi Iwai 		}
1672247d85eeSTakashi Iwai 
1673247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1674247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1675352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1676352f7f91STakashi Iwai 			if (err < 0)
1677352f7f91STakashi Iwai 				return err;
1678352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1679352f7f91STakashi Iwai 			if (err < 0)
1680352f7f91STakashi Iwai 				return err;
1681352f7f91STakashi Iwai 		} else {
1682352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1683352f7f91STakashi Iwai 			if (err < 0)
1684352f7f91STakashi Iwai 				return err;
1685352f7f91STakashi Iwai 		}
1686352f7f91STakashi Iwai 	}
1687352f7f91STakashi Iwai 	return 0;
1688352f7f91STakashi Iwai }
1689352f7f91STakashi Iwai 
1690c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1691196c1766STakashi Iwai 			    const char *pfx, int cidx)
1692352f7f91STakashi Iwai {
1693352f7f91STakashi Iwai 	struct nid_path *path;
1694352f7f91STakashi Iwai 	int err;
1695352f7f91STakashi Iwai 
1696196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1697352f7f91STakashi Iwai 	if (!path)
1698352f7f91STakashi Iwai 		return 0;
1699352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1700352f7f91STakashi Iwai 	if (err < 0)
1701352f7f91STakashi Iwai 		return err;
1702352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1703352f7f91STakashi Iwai 	if (err < 0)
1704352f7f91STakashi Iwai 		return err;
1705352f7f91STakashi Iwai 	return 0;
1706352f7f91STakashi Iwai }
1707352f7f91STakashi Iwai 
1708352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1709352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1710196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1711352f7f91STakashi Iwai {
1712c2c80383STakashi Iwai 	int i;
1713352f7f91STakashi Iwai 
1714352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1715c2c80383STakashi Iwai 		const char *name;
1716c2c80383STakashi Iwai 		char tmp[44];
1717c2c80383STakashi Iwai 		int err, idx = 0;
1718c2c80383STakashi Iwai 
1719c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1720c2c80383STakashi Iwai 			name = "Bass Speaker";
1721c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1722c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1723352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1724c2c80383STakashi Iwai 			name = tmp;
1725352f7f91STakashi Iwai 		} else {
1726c2c80383STakashi Iwai 			name = pfx;
1727c2c80383STakashi Iwai 			idx = i;
1728352f7f91STakashi Iwai 		}
1729c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1730352f7f91STakashi Iwai 		if (err < 0)
1731352f7f91STakashi Iwai 			return err;
1732352f7f91STakashi Iwai 	}
1733352f7f91STakashi Iwai 	return 0;
1734352f7f91STakashi Iwai }
1735352f7f91STakashi Iwai 
1736352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1737352f7f91STakashi Iwai {
1738352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1739352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1740196c1766STakashi Iwai 				 spec->hp_paths,
1741352f7f91STakashi Iwai 				 "Headphone");
1742352f7f91STakashi Iwai }
1743352f7f91STakashi Iwai 
1744352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1745352f7f91STakashi Iwai {
1746352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1747352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1748196c1766STakashi Iwai 				 spec->speaker_paths,
1749352f7f91STakashi Iwai 				 "Speaker");
1750352f7f91STakashi Iwai }
1751352f7f91STakashi Iwai 
1752352f7f91STakashi Iwai /*
175338cf6f1aSTakashi Iwai  * independent HP controls
175438cf6f1aSTakashi Iwai  */
175538cf6f1aSTakashi Iwai 
175638cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
175738cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
175838cf6f1aSTakashi Iwai {
175938cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
176038cf6f1aSTakashi Iwai }
176138cf6f1aSTakashi Iwai 
176238cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
176338cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
176438cf6f1aSTakashi Iwai {
176538cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
176638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
176738cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
176838cf6f1aSTakashi Iwai 	return 0;
176938cf6f1aSTakashi Iwai }
177038cf6f1aSTakashi Iwai 
177138cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
177238cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
177338cf6f1aSTakashi Iwai {
177438cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
177538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
177638cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
177738cf6f1aSTakashi Iwai 	int ret = 0;
177838cf6f1aSTakashi Iwai 
177938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
178038cf6f1aSTakashi Iwai 	if (spec->active_streams) {
178138cf6f1aSTakashi Iwai 		ret = -EBUSY;
178238cf6f1aSTakashi Iwai 		goto unlock;
178338cf6f1aSTakashi Iwai 	}
178438cf6f1aSTakashi Iwai 
178538cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
178638cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
178738cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
178838cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
178938cf6f1aSTakashi Iwai 		else
179038cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
179138cf6f1aSTakashi Iwai 		ret = 1;
179238cf6f1aSTakashi Iwai 	}
179338cf6f1aSTakashi Iwai  unlock:
179438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
179538cf6f1aSTakashi Iwai 	return ret;
179638cf6f1aSTakashi Iwai }
179738cf6f1aSTakashi Iwai 
179838cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
179938cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
180038cf6f1aSTakashi Iwai 	.name = "Independent HP",
180138cf6f1aSTakashi Iwai 	.info = indep_hp_info,
180238cf6f1aSTakashi Iwai 	.get = indep_hp_get,
180338cf6f1aSTakashi Iwai 	.put = indep_hp_put,
180438cf6f1aSTakashi Iwai };
180538cf6f1aSTakashi Iwai 
180638cf6f1aSTakashi Iwai 
180738cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
180838cf6f1aSTakashi Iwai {
180938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
181038cf6f1aSTakashi Iwai 
181138cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
181238cf6f1aSTakashi Iwai 		return 0;
181338cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
181438cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
181538cf6f1aSTakashi Iwai 		return 0;
181638cf6f1aSTakashi Iwai 	}
181738cf6f1aSTakashi Iwai 
181838cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
181938cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
182038cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
182138cf6f1aSTakashi Iwai 		return -ENOMEM;
182238cf6f1aSTakashi Iwai 	return 0;
182338cf6f1aSTakashi Iwai }
182438cf6f1aSTakashi Iwai 
182538cf6f1aSTakashi Iwai /*
1826352f7f91STakashi Iwai  * channel mode enum control
1827352f7f91STakashi Iwai  */
1828352f7f91STakashi Iwai 
1829352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1830352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1831352f7f91STakashi Iwai {
1832352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1833352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1834a07a949bSTakashi Iwai 	int chs;
1835352f7f91STakashi Iwai 
1836352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1837352f7f91STakashi Iwai 	uinfo->count = 1;
1838352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1839352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1840352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1841a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
1842a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
1843352f7f91STakashi Iwai 	return 0;
1844352f7f91STakashi Iwai }
1845352f7f91STakashi Iwai 
1846352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1847352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1848352f7f91STakashi Iwai {
1849352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1850352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1851a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
1852a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
1853352f7f91STakashi Iwai 	return 0;
1854352f7f91STakashi Iwai }
1855352f7f91STakashi Iwai 
1856196c1766STakashi Iwai static inline struct nid_path *
1857196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1858196c1766STakashi Iwai {
1859196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1860196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1861196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1862196c1766STakashi Iwai }
1863196c1766STakashi Iwai 
1864a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
1865a5cc2509STakashi Iwai 
1866352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1867352f7f91STakashi Iwai {
1868352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1869352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1870352f7f91STakashi Iwai 	struct nid_path *path;
1871352f7f91STakashi Iwai 
1872196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1873352f7f91STakashi Iwai 	if (!path)
1874352f7f91STakashi Iwai 		return -EINVAL;
1875352f7f91STakashi Iwai 
1876352f7f91STakashi Iwai 	if (path->active == output)
1877352f7f91STakashi Iwai 		return 0;
1878352f7f91STakashi Iwai 
1879352f7f91STakashi Iwai 	if (output) {
18802c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
1881352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1882d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1883352f7f91STakashi Iwai 	} else {
1884d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1885352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
18862c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
1887352f7f91STakashi Iwai 	}
1888a365fed9STakashi Iwai 
1889a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
1890a5cc2509STakashi Iwai 	update_automute_all(codec);
1891a365fed9STakashi Iwai 
1892352f7f91STakashi Iwai 	return 0;
1893352f7f91STakashi Iwai }
1894352f7f91STakashi Iwai 
1895352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1896352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1897352f7f91STakashi Iwai {
1898352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1899352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1900352f7f91STakashi Iwai 	int i, ch;
1901352f7f91STakashi Iwai 
1902352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1903352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1904352f7f91STakashi Iwai 		return -EINVAL;
1905a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
1906352f7f91STakashi Iwai 		return 0;
1907a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
1908352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1909352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1910352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1911352f7f91STakashi Iwai 					  spec->const_channel_count);
1912352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1913352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1914352f7f91STakashi Iwai 	return 1;
1915352f7f91STakashi Iwai }
1916352f7f91STakashi Iwai 
1917352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1918352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1919352f7f91STakashi Iwai 	.name = "Channel Mode",
1920352f7f91STakashi Iwai 	.info = ch_mode_info,
1921352f7f91STakashi Iwai 	.get = ch_mode_get,
1922352f7f91STakashi Iwai 	.put = ch_mode_put,
1923352f7f91STakashi Iwai };
1924352f7f91STakashi Iwai 
1925352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1926352f7f91STakashi Iwai {
1927352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1928352f7f91STakashi Iwai 
1929352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
193012c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1931352f7f91STakashi Iwai 			return -ENOMEM;
1932352f7f91STakashi Iwai 	}
1933352f7f91STakashi Iwai 	return 0;
1934352f7f91STakashi Iwai }
1935352f7f91STakashi Iwai 
1936352f7f91STakashi Iwai /*
1937c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1938c30aa7b2STakashi Iwai  */
1939c30aa7b2STakashi Iwai 
1940c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1941c30aa7b2STakashi Iwai 
1942c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1943c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1944c30aa7b2STakashi Iwai {
1945c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1946c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1947c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1948c30aa7b2STakashi Iwai 	return 0;
1949c30aa7b2STakashi Iwai }
1950c30aa7b2STakashi Iwai 
1951c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1952c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1953c30aa7b2STakashi Iwai {
1954c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1955c30aa7b2STakashi Iwai 
1956c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1957c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1958c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1959c30aa7b2STakashi Iwai 		return;
1960c30aa7b2STakashi Iwai 	if (do_mix) {
1961c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1962c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1963c30aa7b2STakashi Iwai 	} else {
1964c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1965c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1966c30aa7b2STakashi Iwai 	}
1967c30aa7b2STakashi Iwai }
1968c30aa7b2STakashi Iwai 
1969c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1970c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1971c30aa7b2STakashi Iwai {
1972c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1973c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1974c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
1975c30aa7b2STakashi Iwai 
1976c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
1977c30aa7b2STakashi Iwai 		return 0;
1978c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
1979c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
1980c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
1981c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
1982c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
1983c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
1984c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
1985c30aa7b2STakashi Iwai 	return 1;
1986c30aa7b2STakashi Iwai }
1987c30aa7b2STakashi Iwai 
1988c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
1989c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1990c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
1991c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
1992c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
1993c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
1994c30aa7b2STakashi Iwai };
1995c30aa7b2STakashi Iwai 
1996c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
1997c30aa7b2STakashi Iwai {
1998c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1999c30aa7b2STakashi Iwai 
2000c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2001c30aa7b2STakashi Iwai 		return 0;
2002c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2003c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2004c30aa7b2STakashi Iwai 		return 0;
2005c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2006c30aa7b2STakashi Iwai 		return -ENOMEM;
2007c30aa7b2STakashi Iwai 	return 0;
2008c30aa7b2STakashi Iwai }
2009c30aa7b2STakashi Iwai 
2010c30aa7b2STakashi Iwai /*
2011352f7f91STakashi Iwai  * shared headphone/mic handling
2012352f7f91STakashi Iwai  */
2013352f7f91STakashi Iwai 
2014352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2015352f7f91STakashi Iwai 
2016352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2017352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
2018352f7f91STakashi Iwai {
2019352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2020352f7f91STakashi Iwai 	unsigned int val;
2021352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
2022352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
2023352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
2024352f7f91STakashi Iwai 	 */
2025352f7f91STakashi Iwai 
2026352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2027352f7f91STakashi Iwai 
2028352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
2029352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
2030352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2031352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2032352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2033352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
20347594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
20357594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
2036352f7f91STakashi Iwai 	}
2037352f7f91STakashi Iwai 
2038352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
20392c12c30dSTakashi Iwai 	set_pin_target(codec, pin, val, true);
2040352f7f91STakashi Iwai 
2041352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
2042352f7f91STakashi Iwai 	call_update_outputs(codec);
2043352f7f91STakashi Iwai }
2044352f7f91STakashi Iwai 
2045352f7f91STakashi Iwai /* create a shared input with the headphone out */
2046352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
2047352f7f91STakashi Iwai {
2048352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2049352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2050352f7f91STakashi Iwai 	unsigned int defcfg;
2051352f7f91STakashi Iwai 	hda_nid_t nid;
2052352f7f91STakashi Iwai 
2053352f7f91STakashi Iwai 	/* only one internal input pin? */
2054352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
2055352f7f91STakashi Iwai 		return 0;
2056352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2057352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2058352f7f91STakashi Iwai 		return 0;
2059352f7f91STakashi Iwai 
2060352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2061352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2062352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2063352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2064352f7f91STakashi Iwai 	else
2065352f7f91STakashi Iwai 		return 0; /* both not available */
2066352f7f91STakashi Iwai 
2067352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2068352f7f91STakashi Iwai 		return 0; /* no input */
2069352f7f91STakashi Iwai 
2070352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
2071352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
2072352f7f91STakashi Iwai 	cfg->num_inputs = 2;
2073352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
2074352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2075352f7f91STakashi Iwai 	return 0;
2076352f7f91STakashi Iwai }
2077352f7f91STakashi Iwai 
2078978e77e7STakashi Iwai /*
2079978e77e7STakashi Iwai  * output jack mode
2080978e77e7STakashi Iwai  */
2081978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2082978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2083978e77e7STakashi Iwai {
2084978e77e7STakashi Iwai 	static const char * const texts[] = {
2085978e77e7STakashi Iwai 		"Line Out", "Headphone Out",
2086978e77e7STakashi Iwai 	};
2087978e77e7STakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
2088978e77e7STakashi Iwai }
2089978e77e7STakashi Iwai 
2090978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2091978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2092978e77e7STakashi Iwai {
2093978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2094978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2095978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2096978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2097978e77e7STakashi Iwai 	else
2098978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2099978e77e7STakashi Iwai 	return 0;
2100978e77e7STakashi Iwai }
2101978e77e7STakashi Iwai 
2102978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2103978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2104978e77e7STakashi Iwai {
2105978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2106978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2107978e77e7STakashi Iwai 	unsigned int val;
2108978e77e7STakashi Iwai 
2109978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2110978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2111978e77e7STakashi Iwai 		return 0;
2112978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2113978e77e7STakashi Iwai 	return 1;
2114978e77e7STakashi Iwai }
2115978e77e7STakashi Iwai 
2116978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2117978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2118978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2119978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2120978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2121978e77e7STakashi Iwai };
2122978e77e7STakashi Iwai 
2123978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2124978e77e7STakashi Iwai {
2125978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2126978e77e7STakashi Iwai 	int i;
2127978e77e7STakashi Iwai 
2128978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2129978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2130978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2131978e77e7STakashi Iwai 			return true;
2132978e77e7STakashi Iwai 	}
2133978e77e7STakashi Iwai 	return false;
2134978e77e7STakashi Iwai }
2135978e77e7STakashi Iwai 
2136978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2137978e77e7STakashi Iwai 			       char *name, size_t name_len)
2138978e77e7STakashi Iwai {
2139978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2140978e77e7STakashi Iwai 	int idx = 0;
2141978e77e7STakashi Iwai 
2142978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2143978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2144978e77e7STakashi Iwai 
2145978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2146978e77e7STakashi Iwai 		;
2147978e77e7STakashi Iwai }
2148978e77e7STakashi Iwai 
2149978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2150978e77e7STakashi Iwai 				 hda_nid_t *pins)
2151978e77e7STakashi Iwai {
2152978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2153978e77e7STakashi Iwai 	int i;
2154978e77e7STakashi Iwai 
2155978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2156978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2157978e77e7STakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2158978e77e7STakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
2159978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2160978e77e7STakashi Iwai 			char name[44];
2161978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2162978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2163978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2164978e77e7STakashi Iwai 			if (!knew)
2165978e77e7STakashi Iwai 				return -ENOMEM;
2166978e77e7STakashi Iwai 			knew->private_value = pin;
2167978e77e7STakashi Iwai 		}
2168978e77e7STakashi Iwai 	}
2169978e77e7STakashi Iwai 
2170978e77e7STakashi Iwai 	return 0;
2171978e77e7STakashi Iwai }
2172978e77e7STakashi Iwai 
217329476558STakashi Iwai /*
217429476558STakashi Iwai  * input jack mode
217529476558STakashi Iwai  */
217629476558STakashi Iwai 
217729476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
217829476558STakashi Iwai #define NUM_VREFS	6
217929476558STakashi Iwai 
218029476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
218129476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
218229476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
218329476558STakashi Iwai };
218429476558STakashi Iwai 
218529476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
218629476558STakashi Iwai {
218729476558STakashi Iwai 	unsigned int pincap;
218829476558STakashi Iwai 
218929476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
219029476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
219129476558STakashi Iwai 	/* filter out unusual vrefs */
219229476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
219329476558STakashi Iwai 	return pincap;
219429476558STakashi Iwai }
219529476558STakashi Iwai 
219629476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
219729476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
219829476558STakashi Iwai {
219929476558STakashi Iwai 	unsigned int i, n = 0;
220029476558STakashi Iwai 
220129476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
220229476558STakashi Iwai 		if (vref_caps & (1 << i)) {
220329476558STakashi Iwai 			if (n == item_idx)
220429476558STakashi Iwai 				return i;
220529476558STakashi Iwai 			n++;
220629476558STakashi Iwai 		}
220729476558STakashi Iwai 	}
220829476558STakashi Iwai 	return 0;
220929476558STakashi Iwai }
221029476558STakashi Iwai 
221129476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
221229476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
221329476558STakashi Iwai {
221429476558STakashi Iwai 	unsigned int i, n = 0;
221529476558STakashi Iwai 
221629476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
221729476558STakashi Iwai 		if (i == idx)
221829476558STakashi Iwai 			return n;
221929476558STakashi Iwai 		if (vref_caps & (1 << i))
222029476558STakashi Iwai 			n++;
222129476558STakashi Iwai 	}
222229476558STakashi Iwai 	return 0;
222329476558STakashi Iwai }
222429476558STakashi Iwai 
222529476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
222629476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
222729476558STakashi Iwai {
222829476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
222929476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
223029476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
223129476558STakashi Iwai 
223229476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
223329476558STakashi Iwai 				 vref_texts);
223429476558STakashi Iwai 	/* set the right text */
223529476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
223629476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
223729476558STakashi Iwai 	return 0;
223829476558STakashi Iwai }
223929476558STakashi Iwai 
224029476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
224129476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
224229476558STakashi Iwai {
224329476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
224429476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
224529476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
224629476558STakashi Iwai 	unsigned int idx;
224729476558STakashi Iwai 
224829476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
224929476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
225029476558STakashi Iwai 	return 0;
225129476558STakashi Iwai }
225229476558STakashi Iwai 
225329476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
225429476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
225529476558STakashi Iwai {
225629476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
225729476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
225829476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
225929476558STakashi Iwai 	unsigned int val, idx;
226029476558STakashi Iwai 
226129476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
226229476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
226329476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
226429476558STakashi Iwai 		return 0;
226529476558STakashi Iwai 
226629476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
226729476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
226829476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
226929476558STakashi Iwai 	return 1;
227029476558STakashi Iwai }
227129476558STakashi Iwai 
227229476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
227329476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
227429476558STakashi Iwai 	.info = in_jack_mode_info,
227529476558STakashi Iwai 	.get = in_jack_mode_get,
227629476558STakashi Iwai 	.put = in_jack_mode_put,
227729476558STakashi Iwai };
227829476558STakashi Iwai 
227929476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
228029476558STakashi Iwai {
228129476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
228229476558STakashi Iwai 	unsigned int defcfg;
228329476558STakashi Iwai 	struct snd_kcontrol_new *knew;
228429476558STakashi Iwai 	char name[44];
228529476558STakashi Iwai 
228629476558STakashi Iwai 	/* no jack mode for fixed pins */
228729476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
228829476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
228929476558STakashi Iwai 		return 0;
229029476558STakashi Iwai 
229129476558STakashi Iwai 	/* no multiple vref caps? */
229229476558STakashi Iwai 	if (hweight32(get_vref_caps(codec, pin)) <= 1)
229329476558STakashi Iwai 		return 0;
229429476558STakashi Iwai 
229529476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
229629476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
229729476558STakashi Iwai 	if (!knew)
229829476558STakashi Iwai 		return -ENOMEM;
229929476558STakashi Iwai 	knew->private_value = pin;
230029476558STakashi Iwai 	return 0;
230129476558STakashi Iwai }
230229476558STakashi Iwai 
2303352f7f91STakashi Iwai 
2304352f7f91STakashi Iwai /*
2305352f7f91STakashi Iwai  * Parse input paths
2306352f7f91STakashi Iwai  */
2307352f7f91STakashi Iwai 
2308352f7f91STakashi Iwai #ifdef CONFIG_PM
2309352f7f91STakashi Iwai /* add the powersave loopback-list entry */
2310352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2311352f7f91STakashi Iwai {
2312352f7f91STakashi Iwai 	struct hda_amp_list *list;
2313352f7f91STakashi Iwai 
2314352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
2315352f7f91STakashi Iwai 		return;
2316352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
2317352f7f91STakashi Iwai 	list->nid = mix;
2318352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2319352f7f91STakashi Iwai 	list->idx = idx;
2320352f7f91STakashi Iwai 	spec->num_loopbacks++;
2321cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
2322cb53c626STakashi Iwai }
2323cb53c626STakashi Iwai #else
2324352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
2325cb53c626STakashi Iwai #endif
2326cb53c626STakashi Iwai 
2327352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2328196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2329196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2330352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
23311da177e4SLinus Torvalds {
2332352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2333352f7f91STakashi Iwai 	struct nid_path *path;
2334352f7f91STakashi Iwai 	unsigned int val;
2335352f7f91STakashi Iwai 	int err, idx;
23361da177e4SLinus Torvalds 
2337352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
2338352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
2339352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
2340352f7f91STakashi Iwai 
23413ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2342352f7f91STakashi Iwai 	if (!path)
2343352f7f91STakashi Iwai 		return -EINVAL;
23440c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2345196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2346352f7f91STakashi Iwai 
2347352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
2348352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
2349352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2350352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
2351d13bd412STakashi Iwai 		if (err < 0)
23521da177e4SLinus Torvalds 			return err;
2353352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
23541da177e4SLinus Torvalds 	}
23551da177e4SLinus Torvalds 
2356352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
2357352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2358352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
2359d13bd412STakashi Iwai 		if (err < 0)
23601da177e4SLinus Torvalds 			return err;
2361352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
23621da177e4SLinus Torvalds 	}
23631da177e4SLinus Torvalds 
2364352f7f91STakashi Iwai 	path->active = true;
2365352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
2366352f7f91STakashi Iwai 	return 0;
23671da177e4SLinus Torvalds }
23681da177e4SLinus Torvalds 
2369352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
23701da177e4SLinus Torvalds {
2371352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2372352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2373352f7f91STakashi Iwai }
2374352f7f91STakashi Iwai 
2375352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2376352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2377352f7f91STakashi Iwai {
2378352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2379352f7f91STakashi Iwai 	hda_nid_t nid;
2380352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2381352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2382352f7f91STakashi Iwai 	int i, nums = 0;
2383352f7f91STakashi Iwai 
2384352f7f91STakashi Iwai 	nid = codec->start_nid;
2385352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2386352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2387352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2388352f7f91STakashi Iwai 
2389352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2390352f7f91STakashi Iwai 			continue;
2391352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2392352f7f91STakashi Iwai 		if (++nums >= max_nums)
2393352f7f91STakashi Iwai 			break;
2394352f7f91STakashi Iwai 	}
2395352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
23960ffd534eSTakashi Iwai 
23970ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
23980ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
23990ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
24000ffd534eSTakashi Iwai 
2401352f7f91STakashi Iwai 	return nums;
2402352f7f91STakashi Iwai }
2403352f7f91STakashi Iwai 
2404352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2405352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2406352f7f91STakashi Iwai  */
2407352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2408352f7f91STakashi Iwai {
2409352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2410352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
24113a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2412352f7f91STakashi Iwai 	int i, n, nums;
2413352f7f91STakashi Iwai 
2414352f7f91STakashi Iwai  again:
2415352f7f91STakashi Iwai 	nums = 0;
24163a65bcdcSTakashi Iwai 	ok_bits = 0;
2417352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2418352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
24193a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2420352f7f91STakashi Iwai 				break;
2421352f7f91STakashi Iwai 		}
24223a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
24233a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
24243a65bcdcSTakashi Iwai 			nums++;
24253a65bcdcSTakashi Iwai 		}
2426352f7f91STakashi Iwai 	}
2427352f7f91STakashi Iwai 
24283a65bcdcSTakashi Iwai 	if (!ok_bits) {
2429352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
2430352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
2431352f7f91STakashi Iwai 			imux->num_items = 1;
2432352f7f91STakashi Iwai 			goto again;
2433352f7f91STakashi Iwai 		}
2434352f7f91STakashi Iwai 
2435352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2436352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2437352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
24383a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2439352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2440352f7f91STakashi Iwai 					break;
2441352f7f91STakashi Iwai 				}
2442352f7f91STakashi Iwai 			}
2443352f7f91STakashi Iwai 		}
2444352f7f91STakashi Iwai 
2445352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2446352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2447352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
24483a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
24493a65bcdcSTakashi Iwai 		nums = 0;
24503a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
24513a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
24523a65bcdcSTakashi Iwai 				continue;
24533a65bcdcSTakashi Iwai 			if (n != nums) {
24543a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2455980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2456980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2457980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
24583a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
24593a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
24603a65bcdcSTakashi Iwai 				}
2461980428ceSTakashi Iwai 			}
24623a65bcdcSTakashi Iwai 			nums++;
24633a65bcdcSTakashi Iwai 		}
2464352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2465352f7f91STakashi Iwai 	}
2466352f7f91STakashi Iwai 
2467352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
2468352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2469352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2470352f7f91STakashi Iwai 	}
2471352f7f91STakashi Iwai 
2472352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2473352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
2474352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
2475352f7f91STakashi Iwai 
24761da177e4SLinus Torvalds 	return 0;
24771da177e4SLinus Torvalds }
24781da177e4SLinus Torvalds 
2479f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
2480f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
24819dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
24829dba205bSTakashi Iwai 				const char *label, int anchor)
2483f3fc0b0bSTakashi Iwai {
2484f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2485f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2486f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
2487f3fc0b0bSTakashi Iwai 	bool imux_added = false;
2488f3fc0b0bSTakashi Iwai 	int c;
2489f3fc0b0bSTakashi Iwai 
2490f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
2491f3fc0b0bSTakashi Iwai 		struct nid_path *path;
2492f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
2493f3fc0b0bSTakashi Iwai 
2494f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
2495f3fc0b0bSTakashi Iwai 			continue;
2496f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
2497f3fc0b0bSTakashi Iwai 		if (!path)
2498f3fc0b0bSTakashi Iwai 			continue;
2499f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
2500f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
2501f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
2502f3fc0b0bSTakashi Iwai 
2503f3fc0b0bSTakashi Iwai 		if (!imux_added) {
2504f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
25059dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
2506f3fc0b0bSTakashi Iwai 			imux_added = true;
2507f3fc0b0bSTakashi Iwai 		}
2508f3fc0b0bSTakashi Iwai 	}
2509f3fc0b0bSTakashi Iwai 
2510f3fc0b0bSTakashi Iwai 	return 0;
2511f3fc0b0bSTakashi Iwai }
2512f3fc0b0bSTakashi Iwai 
25131da177e4SLinus Torvalds /*
2514352f7f91STakashi Iwai  * create playback/capture controls for input pins
25151da177e4SLinus Torvalds  */
25169dba205bSTakashi Iwai 
25179dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
25189dba205bSTakashi Iwai 
2519352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2520a7da6ce5STakashi Iwai {
2521352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2522352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2523352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2524352f7f91STakashi Iwai 	int num_adcs;
2525f3fc0b0bSTakashi Iwai 	int i, err, type_idx = 0;
2526352f7f91STakashi Iwai 	const char *prev_label = NULL;
25272c12c30dSTakashi Iwai 	unsigned int val;
2528a7da6ce5STakashi Iwai 
2529352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2530352f7f91STakashi Iwai 	if (num_adcs < 0)
2531352f7f91STakashi Iwai 		return 0;
2532352f7f91STakashi Iwai 
2533352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2534352f7f91STakashi Iwai 		hda_nid_t pin;
2535352f7f91STakashi Iwai 		const char *label;
2536352f7f91STakashi Iwai 
2537352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2538352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2539352f7f91STakashi Iwai 			continue;
2540352f7f91STakashi Iwai 
2541352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2542352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2543352f7f91STakashi Iwai 			type_idx++;
2544352f7f91STakashi Iwai 		else
2545352f7f91STakashi Iwai 			type_idx = 0;
2546352f7f91STakashi Iwai 		prev_label = label;
2547352f7f91STakashi Iwai 
25482c12c30dSTakashi Iwai 		val = PIN_IN;
25492c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
25502c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
25512c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, false);
25522c12c30dSTakashi Iwai 
2553352f7f91STakashi Iwai 		if (mixer) {
2554352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2555196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2556352f7f91STakashi Iwai 						       label, type_idx, mixer);
2557a7da6ce5STakashi Iwai 				if (err < 0)
2558a7da6ce5STakashi Iwai 					return err;
2559a7da6ce5STakashi Iwai 			}
2560352f7f91STakashi Iwai 		}
2561352f7f91STakashi Iwai 
25629dba205bSTakashi Iwai 		err = parse_capture_source(codec, pin, i,
25639dba205bSTakashi Iwai 					   num_adcs, label, -mixer);
2564f3fc0b0bSTakashi Iwai 		if (err < 0)
2565f3fc0b0bSTakashi Iwai 			return err;
256629476558STakashi Iwai 
256729476558STakashi Iwai 		if (spec->add_in_jack_modes) {
256829476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
256929476558STakashi Iwai 			if (err < 0)
257029476558STakashi Iwai 				return err;
257129476558STakashi Iwai 		}
2572352f7f91STakashi Iwai 	}
2573f3fc0b0bSTakashi Iwai 
2574f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
25759dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
2576f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
2577f3fc0b0bSTakashi Iwai 		if (err < 0)
2578f3fc0b0bSTakashi Iwai 			return err;
2579352f7f91STakashi Iwai 	}
2580352f7f91STakashi Iwai 
2581a7da6ce5STakashi Iwai 	return 0;
2582a7da6ce5STakashi Iwai }
2583a7da6ce5STakashi Iwai 
25841da177e4SLinus Torvalds 
2585352f7f91STakashi Iwai /*
2586352f7f91STakashi Iwai  * input source mux
2587352f7f91STakashi Iwai  */
2588352f7f91STakashi Iwai 
2589c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
2590c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
2591352f7f91STakashi Iwai {
2592352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2593b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
2594b56fa1edSDavid Henningsson 		snd_BUG();
2595b56fa1edSDavid Henningsson 		return NULL;
2596b56fa1edSDavid Henningsson 	}
2597352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2598352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2599b56fa1edSDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_OUTS) {
2600b56fa1edSDavid Henningsson 		snd_BUG();
2601b56fa1edSDavid Henningsson 		return NULL;
2602b56fa1edSDavid Henningsson 	}
2603c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
260497ec558aSTakashi Iwai }
2605352f7f91STakashi Iwai 
2606352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2607352f7f91STakashi Iwai 		      unsigned int idx);
2608352f7f91STakashi Iwai 
2609352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2610352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2611352f7f91STakashi Iwai {
2612352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2613352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2614352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2615352f7f91STakashi Iwai }
2616352f7f91STakashi Iwai 
2617352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2618352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2619352f7f91STakashi Iwai {
2620352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2621352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2622a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2623352f7f91STakashi Iwai 
2624352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
26251da177e4SLinus Torvalds 	return 0;
26261da177e4SLinus Torvalds }
26271da177e4SLinus Torvalds 
2628352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2629352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
26301da177e4SLinus Torvalds {
2631352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2632a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2633352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2634352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2635352f7f91STakashi Iwai }
2636352f7f91STakashi Iwai 
2637352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
26381da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2639352f7f91STakashi Iwai 	.name = "Input Source",
2640352f7f91STakashi Iwai 	.info = mux_enum_info,
2641352f7f91STakashi Iwai 	.get = mux_enum_get,
2642352f7f91STakashi Iwai 	.put = mux_enum_put,
26431da177e4SLinus Torvalds };
2644071c73adSTakashi Iwai 
264547d46abbSTakashi Iwai /*
264647d46abbSTakashi Iwai  * capture volume and capture switch ctls
264747d46abbSTakashi Iwai  */
264847d46abbSTakashi Iwai 
2649352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2650352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2651071c73adSTakashi Iwai 
265247d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2653352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2654352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2655352f7f91STakashi Iwai 			  put_call_t func, int type)
2656352f7f91STakashi Iwai {
2657352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2658352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2659352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2660352f7f91STakashi Iwai 	struct nid_path *path;
2661352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2662071c73adSTakashi Iwai 
2663352f7f91STakashi Iwai 	imux = &spec->input_mux;
2664a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
2665352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
266647d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
266747d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
266847d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
266947d46abbSTakashi Iwai 	 */
2670352f7f91STakashi Iwai 	codec->cached_write = 1;
2671352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2672c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
2673c697b716STakashi Iwai 		if (!path || !path->ctls[type])
2674352f7f91STakashi Iwai 			continue;
2675352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2676352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2677352f7f91STakashi Iwai 		if (err < 0)
2678352f7f91STakashi Iwai 			goto error;
2679352f7f91STakashi Iwai 	}
2680352f7f91STakashi Iwai  error:
2681352f7f91STakashi Iwai 	codec->cached_write = 0;
2682352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
268347d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2684352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2685352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
2686352f7f91STakashi Iwai 	return err;
2687352f7f91STakashi Iwai }
2688352f7f91STakashi Iwai 
2689352f7f91STakashi Iwai /* capture volume ctl callbacks */
2690352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2691352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2692352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2693352f7f91STakashi Iwai 
2694352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2695352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2696352f7f91STakashi Iwai {
2697352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2698352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2699352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2700352f7f91STakashi Iwai }
2701352f7f91STakashi Iwai 
2702352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2703352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2704352f7f91STakashi Iwai 	.name = "Capture Volume",
2705352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2706352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2707352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2708352f7f91STakashi Iwai 	.info = cap_vol_info,
2709352f7f91STakashi Iwai 	.get = cap_vol_get,
2710352f7f91STakashi Iwai 	.put = cap_vol_put,
2711352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2712352f7f91STakashi Iwai };
2713352f7f91STakashi Iwai 
2714352f7f91STakashi Iwai /* capture switch ctl callbacks */
2715352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2716352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2717352f7f91STakashi Iwai 
2718352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2719352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2720352f7f91STakashi Iwai {
2721ae177c3fSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2722ae177c3fSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2723ae177c3fSTakashi Iwai 	int ret;
2724ae177c3fSTakashi Iwai 
2725ae177c3fSTakashi Iwai 	ret = cap_put_caller(kcontrol, ucontrol,
2726352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2727352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2728ae177c3fSTakashi Iwai 	if (ret < 0)
2729ae177c3fSTakashi Iwai 		return ret;
2730ae177c3fSTakashi Iwai 
2731ae177c3fSTakashi Iwai 	if (spec->capture_switch_hook) {
2732ae177c3fSTakashi Iwai 		bool enable = (ucontrol->value.integer.value[0] ||
2733ae177c3fSTakashi Iwai 			       ucontrol->value.integer.value[1]);
2734ae177c3fSTakashi Iwai 		spec->capture_switch_hook(codec, enable);
2735ae177c3fSTakashi Iwai 	}
2736ae177c3fSTakashi Iwai 
2737ae177c3fSTakashi Iwai 	return ret;
2738352f7f91STakashi Iwai }
2739352f7f91STakashi Iwai 
2740352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2741352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2742352f7f91STakashi Iwai 	.name = "Capture Switch",
2743352f7f91STakashi Iwai 	.info = cap_sw_info,
2744352f7f91STakashi Iwai 	.get = cap_sw_get,
2745352f7f91STakashi Iwai 	.put = cap_sw_put,
2746352f7f91STakashi Iwai };
2747352f7f91STakashi Iwai 
2748352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2749352f7f91STakashi Iwai {
2750352f7f91STakashi Iwai 	hda_nid_t nid;
2751352f7f91STakashi Iwai 	int i, depth;
2752352f7f91STakashi Iwai 
2753352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2754352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2755352f7f91STakashi Iwai 		if (depth >= path->depth)
2756352f7f91STakashi Iwai 			return -EINVAL;
2757352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2758352f7f91STakashi Iwai 		nid = path->path[i];
2759352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2760352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2761352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2762352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2763352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2764352f7f91STakashi Iwai 				int idx = path->idx[i];
2765352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2766352f7f91STakashi Iwai 					idx = 0;
2767352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2768352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2769352f7f91STakashi Iwai 			}
2770352f7f91STakashi Iwai 		}
2771352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2772352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2773352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2774352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2775352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2776352f7f91STakashi Iwai 				int idx = path->idx[i];
2777352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2778352f7f91STakashi Iwai 					idx = 0;
2779352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2780352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2781352f7f91STakashi Iwai 			}
2782352f7f91STakashi Iwai 		}
2783352f7f91STakashi Iwai 	}
2784352f7f91STakashi Iwai 	return 0;
2785352f7f91STakashi Iwai }
2786352f7f91STakashi Iwai 
2787352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2788352f7f91STakashi Iwai {
2789352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2790352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2791352f7f91STakashi Iwai 	unsigned int val;
2792352f7f91STakashi Iwai 	int i;
2793352f7f91STakashi Iwai 
2794352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2795352f7f91STakashi Iwai 		return false;
2796352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2797352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2798352f7f91STakashi Iwai 			continue;
2799352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2800352f7f91STakashi Iwai 			return false;
2801352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2802352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2803352f7f91STakashi Iwai 	}
2804352f7f91STakashi Iwai 	return false;
2805352f7f91STakashi Iwai }
2806352f7f91STakashi Iwai 
2807352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2808352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2809352f7f91STakashi Iwai 			      bool inv_dmic)
2810352f7f91STakashi Iwai {
2811352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2812352f7f91STakashi Iwai 	char tmpname[44];
2813352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2814352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2815352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2816352f7f91STakashi Iwai 	int err;
2817352f7f91STakashi Iwai 
2818352f7f91STakashi Iwai 	if (!ctl)
2819352f7f91STakashi Iwai 		return 0;
2820352f7f91STakashi Iwai 
2821352f7f91STakashi Iwai 	if (label)
2822352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2823352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2824352f7f91STakashi Iwai 	else
2825352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2826352f7f91STakashi Iwai 			 "Capture %s", sfx);
2827352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2828352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2829352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2830352f7f91STakashi Iwai 		return err;
2831352f7f91STakashi Iwai 
2832352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2833352f7f91STakashi Iwai 	if (label)
2834352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2835352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2836352f7f91STakashi Iwai 	else
2837352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2838352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2839352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2840352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2841352f7f91STakashi Iwai }
2842352f7f91STakashi Iwai 
2843352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2844352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2845352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2846352f7f91STakashi Iwai 				     bool inv_dmic)
2847352f7f91STakashi Iwai {
2848352f7f91STakashi Iwai 	int err;
2849352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2850352f7f91STakashi Iwai 	if (err < 0)
2851352f7f91STakashi Iwai 		return err;
2852352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2853071c73adSTakashi Iwai 	if (err < 0)
2854071c73adSTakashi Iwai 		return err;
2855071c73adSTakashi Iwai 	return 0;
28561da177e4SLinus Torvalds }
2857071c73adSTakashi Iwai 
2858352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2859352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2860352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2861352f7f91STakashi Iwai {
2862352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2863352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2864352f7f91STakashi Iwai 
2865352f7f91STakashi Iwai 	if (vol_ctl) {
286612c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2867352f7f91STakashi Iwai 		if (!knew)
2868352f7f91STakashi Iwai 			return -ENOMEM;
2869352f7f91STakashi Iwai 		knew->index = idx;
2870352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2871352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2872352f7f91STakashi Iwai 	}
2873352f7f91STakashi Iwai 	if (sw_ctl) {
287412c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2875352f7f91STakashi Iwai 		if (!knew)
2876352f7f91STakashi Iwai 			return -ENOMEM;
2877352f7f91STakashi Iwai 		knew->index = idx;
2878352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2879352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2880352f7f91STakashi Iwai 	}
2881352f7f91STakashi Iwai 	return 0;
2882352f7f91STakashi Iwai }
2883352f7f91STakashi Iwai 
2884352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2885352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2886352f7f91STakashi Iwai {
2887352f7f91STakashi Iwai 	struct nid_path *path;
2888352f7f91STakashi Iwai 	unsigned int ctl;
2889352f7f91STakashi Iwai 	int i;
2890352f7f91STakashi Iwai 
2891c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
2892352f7f91STakashi Iwai 	if (!path)
2893352f7f91STakashi Iwai 		return 0;
2894352f7f91STakashi Iwai 	ctl = path->ctls[type];
2895352f7f91STakashi Iwai 	if (!ctl)
2896352f7f91STakashi Iwai 		return 0;
2897352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2898c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
2899352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2900352f7f91STakashi Iwai 			return 0;
2901352f7f91STakashi Iwai 	}
2902352f7f91STakashi Iwai 	return ctl;
2903352f7f91STakashi Iwai }
2904352f7f91STakashi Iwai 
2905352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2906352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2907352f7f91STakashi Iwai {
2908352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2909352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2910352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2911352f7f91STakashi Iwai 	const char *prev_label = NULL;
2912352f7f91STakashi Iwai 
2913352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2914352f7f91STakashi Iwai 		const char *label;
2915352f7f91STakashi Iwai 		bool inv_dmic;
29169dba205bSTakashi Iwai 
29179dba205bSTakashi Iwai 		if (imux->items[i].index >= spec->autocfg.num_inputs)
29189dba205bSTakashi Iwai 			continue;
29199dba205bSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg,
29209dba205bSTakashi Iwai 						    imux->items[i].index);
2921352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2922352f7f91STakashi Iwai 			type_idx++;
2923352f7f91STakashi Iwai 		else
2924352f7f91STakashi Iwai 			type_idx = 0;
2925352f7f91STakashi Iwai 		prev_label = label;
2926352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2927352f7f91STakashi Iwai 
2928352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2929352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2930352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2931352f7f91STakashi Iwai 						 inv_dmic);
2932d13bd412STakashi Iwai 			if (err < 0)
2933071c73adSTakashi Iwai 				return err;
2934352f7f91STakashi Iwai 		}
2935352f7f91STakashi Iwai 	}
2936071c73adSTakashi Iwai 	return 0;
2937352f7f91STakashi Iwai }
2938071c73adSTakashi Iwai 
2939352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2940352f7f91STakashi Iwai {
2941352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2942352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2943352f7f91STakashi Iwai 	int i, n, nums, err;
2944352f7f91STakashi Iwai 
2945352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2946352f7f91STakashi Iwai 		nums = 1;
2947352f7f91STakashi Iwai 	else
2948352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2949352f7f91STakashi Iwai 
2950352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2951352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2952624d914dSTakashi Iwai 		const char *name;
2953624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2954624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2955352f7f91STakashi Iwai 		if (!knew)
2956352f7f91STakashi Iwai 			return -ENOMEM;
2957352f7f91STakashi Iwai 		knew->count = nums;
2958352f7f91STakashi Iwai 	}
2959352f7f91STakashi Iwai 
2960352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2961352f7f91STakashi Iwai 		bool multi = false;
296299a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
2963352f7f91STakashi Iwai 		bool inv_dmic = false;
2964352f7f91STakashi Iwai 		int vol, sw;
2965352f7f91STakashi Iwai 
2966352f7f91STakashi Iwai 		vol = sw = 0;
2967352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2968352f7f91STakashi Iwai 			struct nid_path *path;
2969c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
2970352f7f91STakashi Iwai 			if (!path)
2971352f7f91STakashi Iwai 				continue;
2972352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2973352f7f91STakashi Iwai 			if (!vol)
2974352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
297599a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
2976352f7f91STakashi Iwai 				multi = true;
297799a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
297899a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
297999a5592dSDavid Henningsson 					multi_cap_vol = true;
298099a5592dSDavid Henningsson 			}
2981352f7f91STakashi Iwai 			if (!sw)
2982352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
298399a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
2984352f7f91STakashi Iwai 				multi = true;
298599a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
298699a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
298799a5592dSDavid Henningsson 					multi_cap_vol = true;
298899a5592dSDavid Henningsson 			}
2989352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2990352f7f91STakashi Iwai 				inv_dmic = true;
2991352f7f91STakashi Iwai 		}
2992352f7f91STakashi Iwai 
2993352f7f91STakashi Iwai 		if (!multi)
2994352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2995352f7f91STakashi Iwai 							inv_dmic);
299699a5592dSDavid Henningsson 		else if (!multi_cap_vol)
2997352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2998352f7f91STakashi Iwai 		else
2999352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3000d13bd412STakashi Iwai 		if (err < 0)
3001071c73adSTakashi Iwai 			return err;
3002071c73adSTakashi Iwai 	}
3003071c73adSTakashi Iwai 
30041da177e4SLinus Torvalds 	return 0;
30051da177e4SLinus Torvalds }
30061da177e4SLinus Torvalds 
3007352f7f91STakashi Iwai /*
3008352f7f91STakashi Iwai  * add mic boosts if needed
3009352f7f91STakashi Iwai  */
3010352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3011352f7f91STakashi Iwai {
3012352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3013352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3014352f7f91STakashi Iwai 	int i, err;
3015352f7f91STakashi Iwai 	int type_idx = 0;
3016352f7f91STakashi Iwai 	hda_nid_t nid;
3017352f7f91STakashi Iwai 	const char *prev_label = NULL;
3018352f7f91STakashi Iwai 
3019352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3020352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
3021352f7f91STakashi Iwai 			break;
3022352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
3023352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
3024352f7f91STakashi Iwai 			const char *label;
30255abd4888STakashi Iwai 			char boost_label[44];
3026352f7f91STakashi Iwai 			struct nid_path *path;
3027352f7f91STakashi Iwai 			unsigned int val;
3028352f7f91STakashi Iwai 
302902aba550SDavid Henningsson 			if (!nid_has_volume(codec, nid, HDA_INPUT))
303002aba550SDavid Henningsson 				continue;
303102aba550SDavid Henningsson 
3032352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
3033352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
3034352f7f91STakashi Iwai 				type_idx++;
3035352f7f91STakashi Iwai 			else
3036352f7f91STakashi Iwai 				type_idx = 0;
3037352f7f91STakashi Iwai 			prev_label = label;
3038352f7f91STakashi Iwai 
3039352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
3040352f7f91STakashi Iwai 				 "%s Boost Volume", label);
3041352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
3042352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
3043352f7f91STakashi Iwai 					  boost_label, type_idx, val);
3044352f7f91STakashi Iwai 			if (err < 0)
3045352f7f91STakashi Iwai 				return err;
3046352f7f91STakashi Iwai 
3047352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
3048352f7f91STakashi Iwai 			if (path)
3049352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
3050352f7f91STakashi Iwai 		}
3051352f7f91STakashi Iwai 	}
3052352f7f91STakashi Iwai 	return 0;
3053352f7f91STakashi Iwai }
3054352f7f91STakashi Iwai 
3055352f7f91STakashi Iwai /*
3056352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3057352f7f91STakashi Iwai  */
3058352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3059352f7f91STakashi Iwai {
3060352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
30610c8c0f56STakashi Iwai 	struct nid_path *path;
3062352f7f91STakashi Iwai 	int i, nums;
30632c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3064352f7f91STakashi Iwai 
3065352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3066352f7f91STakashi Iwai 	nums = 0;
3067352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
30682c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3069352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3070352f7f91STakashi Iwai 		if (!dig_nid)
3071352f7f91STakashi Iwai 			continue;
30723ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
30730c8c0f56STakashi Iwai 		if (!path)
3074352f7f91STakashi Iwai 			continue;
30750c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3076e1284af7STakashi Iwai 		path->active = true;
3077196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
30782c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3079352f7f91STakashi Iwai 		if (!nums) {
3080352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3081352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3082352f7f91STakashi Iwai 		} else {
3083352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3084352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3085352f7f91STakashi Iwai 			break;
3086352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3087352f7f91STakashi Iwai 		}
3088352f7f91STakashi Iwai 		nums++;
3089352f7f91STakashi Iwai 	}
3090352f7f91STakashi Iwai 
3091352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
30922c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3093352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3094352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3095352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3096352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3097352f7f91STakashi Iwai 				continue;
3098352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3099352f7f91STakashi Iwai 				continue;
31002c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3101352f7f91STakashi Iwai 			if (path) {
31020c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3103352f7f91STakashi Iwai 				path->active = true;
3104352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
31052430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
31062c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3107352f7f91STakashi Iwai 				break;
3108352f7f91STakashi Iwai 			}
3109352f7f91STakashi Iwai 		}
3110352f7f91STakashi Iwai 	}
3111352f7f91STakashi Iwai }
3112352f7f91STakashi Iwai 
31131da177e4SLinus Torvalds 
31141da177e4SLinus Torvalds /*
3115352f7f91STakashi Iwai  * input MUX handling
31161da177e4SLinus Torvalds  */
31171da177e4SLinus Torvalds 
3118352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3119352f7f91STakashi Iwai 
3120352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3121352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3122352f7f91STakashi Iwai 		      unsigned int idx)
3123352f7f91STakashi Iwai {
3124352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3125352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3126352f7f91STakashi Iwai 	struct nid_path *path;
3127352f7f91STakashi Iwai 
3128352f7f91STakashi Iwai 	imux = &spec->input_mux;
3129352f7f91STakashi Iwai 	if (!imux->num_items)
31301da177e4SLinus Torvalds 		return 0;
31311da177e4SLinus Torvalds 
3132352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3133352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3134352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3135352f7f91STakashi Iwai 		return 0;
3136352f7f91STakashi Iwai 
3137c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
3138352f7f91STakashi Iwai 	if (!path)
3139352f7f91STakashi Iwai 		return 0;
3140352f7f91STakashi Iwai 	if (path->active)
3141352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
3142352f7f91STakashi Iwai 
3143352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3144352f7f91STakashi Iwai 
3145352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3146352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
3147352f7f91STakashi Iwai 
3148352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3149352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3150352f7f91STakashi Iwai 
3151c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3152352f7f91STakashi Iwai 	if (!path)
3153352f7f91STakashi Iwai 		return 0;
3154352f7f91STakashi Iwai 	if (path->active)
3155352f7f91STakashi Iwai 		return 0;
3156352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3157352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3158352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
31591da177e4SLinus Torvalds 	return 1;
31601da177e4SLinus Torvalds }
31611da177e4SLinus Torvalds 
31621da177e4SLinus Torvalds 
31631da177e4SLinus Torvalds /*
3164352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
31651da177e4SLinus Torvalds  */
3166352f7f91STakashi Iwai 
3167352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3168352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
31691da177e4SLinus Torvalds {
3170352f7f91STakashi Iwai 	int i, present = 0;
31711da177e4SLinus Torvalds 
3172352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3173352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3174352f7f91STakashi Iwai 		if (!nid)
3175352f7f91STakashi Iwai 			break;
31760b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
31770b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
31780b4df931STakashi Iwai 			continue;
3179352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
31801da177e4SLinus Torvalds 	}
3181352f7f91STakashi Iwai 	return present;
31821da177e4SLinus Torvalds }
31831da177e4SLinus Torvalds 
3184352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3185352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
31862c12c30dSTakashi Iwai 			bool mute)
31871da177e4SLinus Torvalds {
3188352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3189352f7f91STakashi Iwai 	int i;
31901da177e4SLinus Torvalds 
3191352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3192352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3193352f7f91STakashi Iwai 		unsigned int val;
3194352f7f91STakashi Iwai 		if (!nid)
3195352f7f91STakashi Iwai 			break;
3196352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3197352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3198352f7f91STakashi Iwai 		 */
31992c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
32002c12c30dSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
32012c12c30dSTakashi Iwai 		else
3202352f7f91STakashi Iwai 			val = 0;
32032c12c30dSTakashi Iwai 		if (!mute)
32042c12c30dSTakashi Iwai 			val |= snd_hda_codec_get_pin_target(codec, nid);
32052c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
32062c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
32072c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
32082c12c30dSTakashi Iwai 		 * init / resume again
32092c12c30dSTakashi Iwai 		 */
32102c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3211d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3212352f7f91STakashi Iwai 	}
3213352f7f91STakashi Iwai }
32141da177e4SLinus Torvalds 
3215352f7f91STakashi Iwai /* Toggle outputs muting */
32165d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3217352f7f91STakashi Iwai {
3218352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3219352f7f91STakashi Iwai 	int on;
3220352f7f91STakashi Iwai 
3221352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3222352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3223352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3224352f7f91STakashi Iwai 	 */
3225352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
3226352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
32272c12c30dSTakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute);
3228352f7f91STakashi Iwai 
3229352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3230352f7f91STakashi Iwai 		on = 0;
3231352f7f91STakashi Iwai 	else
3232352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3233352f7f91STakashi Iwai 	on |= spec->master_mute;
323447b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3235352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
32362c12c30dSTakashi Iwai 		    spec->autocfg.speaker_pins, on);
3237352f7f91STakashi Iwai 
3238352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3239352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3240352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3241352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3242352f7f91STakashi Iwai 		return;
3243352f7f91STakashi Iwai 	if (!spec->automute_lo)
3244352f7f91STakashi Iwai 		on = 0;
3245352f7f91STakashi Iwai 	else
3246352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3247352f7f91STakashi Iwai 	on |= spec->master_mute;
324847b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3249352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
32502c12c30dSTakashi Iwai 		    spec->autocfg.line_out_pins, on);
3251352f7f91STakashi Iwai }
32525d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3253352f7f91STakashi Iwai 
3254352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3255352f7f91STakashi Iwai {
3256352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3257352f7f91STakashi Iwai 	if (spec->automute_hook)
3258352f7f91STakashi Iwai 		spec->automute_hook(codec);
3259352f7f91STakashi Iwai 	else
32605d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
3261352f7f91STakashi Iwai }
3262352f7f91STakashi Iwai 
3263352f7f91STakashi Iwai /* standard HP-automute helper */
32645d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3265352f7f91STakashi Iwai {
3266352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3267352f7f91STakashi Iwai 
3268352f7f91STakashi Iwai 	spec->hp_jack_present =
3269352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3270352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
3271352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3272352f7f91STakashi Iwai 		return;
3273352f7f91STakashi Iwai 	call_update_outputs(codec);
3274352f7f91STakashi Iwai }
32755d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3276352f7f91STakashi Iwai 
3277352f7f91STakashi Iwai /* standard line-out-automute helper */
32785d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3279352f7f91STakashi Iwai {
3280352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3281352f7f91STakashi Iwai 
3282352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3283352f7f91STakashi Iwai 		return;
3284352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3285352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3286352f7f91STakashi Iwai 		return;
3287352f7f91STakashi Iwai 
3288352f7f91STakashi Iwai 	spec->line_jack_present =
3289352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3290352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3291352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3292352f7f91STakashi Iwai 		return;
3293352f7f91STakashi Iwai 	call_update_outputs(codec);
3294352f7f91STakashi Iwai }
32955d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3296352f7f91STakashi Iwai 
3297352f7f91STakashi Iwai /* standard mic auto-switch helper */
32985d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3299352f7f91STakashi Iwai {
3300352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3301352f7f91STakashi Iwai 	int i;
3302352f7f91STakashi Iwai 
3303352f7f91STakashi Iwai 	if (!spec->auto_mic)
3304352f7f91STakashi Iwai 		return;
3305352f7f91STakashi Iwai 
3306352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
33070b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
33080b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
33090b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
33100b4df931STakashi Iwai 			continue;
33110b4df931STakashi Iwai 		if (snd_hda_jack_detect(codec, pin)) {
3312352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3313352f7f91STakashi Iwai 			return;
3314352f7f91STakashi Iwai 		}
3315352f7f91STakashi Iwai 	}
3316352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
33171da177e4SLinus Torvalds }
33185d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
33191da177e4SLinus Torvalds 
3320a5cc2509STakashi Iwai /* update jack retasking */
3321a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec)
3322a5cc2509STakashi Iwai {
3323a5cc2509STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3324a5cc2509STakashi Iwai 
3325a5cc2509STakashi Iwai 	if (spec->hp_automute_hook)
3326a5cc2509STakashi Iwai 		spec->hp_automute_hook(codec, NULL);
3327a5cc2509STakashi Iwai 	else
3328a5cc2509STakashi Iwai 		snd_hda_gen_hp_automute(codec, NULL);
3329a5cc2509STakashi Iwai 	if (spec->line_automute_hook)
3330a5cc2509STakashi Iwai 		spec->line_automute_hook(codec, NULL);
3331a5cc2509STakashi Iwai 	else
3332a5cc2509STakashi Iwai 		snd_hda_gen_line_automute(codec, NULL);
3333a5cc2509STakashi Iwai 	if (spec->mic_autoswitch_hook)
3334a5cc2509STakashi Iwai 		spec->mic_autoswitch_hook(codec, NULL);
3335a5cc2509STakashi Iwai 	else
3336a5cc2509STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, NULL);
3337a5cc2509STakashi Iwai }
3338a5cc2509STakashi Iwai 
33391da177e4SLinus Torvalds /*
3340352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
33411da177e4SLinus Torvalds  */
3342352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
3343352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
3344352f7f91STakashi Iwai {
3345352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3346352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3347352f7f91STakashi Iwai 	static const char * const texts3[] = {
3348352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
33491da177e4SLinus Torvalds 	};
33501da177e4SLinus Torvalds 
3351352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
3352352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
3353352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
3354352f7f91STakashi Iwai }
3355352f7f91STakashi Iwai 
3356352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
3357352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3358352f7f91STakashi Iwai {
3359352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3360352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3361352f7f91STakashi Iwai 	unsigned int val = 0;
3362352f7f91STakashi Iwai 	if (spec->automute_speaker)
3363352f7f91STakashi Iwai 		val++;
3364352f7f91STakashi Iwai 	if (spec->automute_lo)
3365352f7f91STakashi Iwai 		val++;
3366352f7f91STakashi Iwai 
3367352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
3368352f7f91STakashi Iwai 	return 0;
3369352f7f91STakashi Iwai }
3370352f7f91STakashi Iwai 
3371352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
3372352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3373352f7f91STakashi Iwai {
3374352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3375352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3376352f7f91STakashi Iwai 
3377352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
3378352f7f91STakashi Iwai 	case 0:
3379352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
3380352f7f91STakashi Iwai 			return 0;
3381352f7f91STakashi Iwai 		spec->automute_speaker = 0;
3382352f7f91STakashi Iwai 		spec->automute_lo = 0;
3383352f7f91STakashi Iwai 		break;
3384352f7f91STakashi Iwai 	case 1:
3385352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
3386352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
3387352f7f91STakashi Iwai 				return 0;
3388352f7f91STakashi Iwai 			spec->automute_speaker = 1;
3389352f7f91STakashi Iwai 			spec->automute_lo = 0;
3390352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
3391352f7f91STakashi Iwai 			if (spec->automute_lo)
3392352f7f91STakashi Iwai 				return 0;
3393352f7f91STakashi Iwai 			spec->automute_lo = 1;
3394352f7f91STakashi Iwai 		} else
3395352f7f91STakashi Iwai 			return -EINVAL;
3396352f7f91STakashi Iwai 		break;
3397352f7f91STakashi Iwai 	case 2:
3398352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
3399352f7f91STakashi Iwai 			return -EINVAL;
3400352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
3401352f7f91STakashi Iwai 			return 0;
3402352f7f91STakashi Iwai 		spec->automute_speaker = 1;
3403352f7f91STakashi Iwai 		spec->automute_lo = 1;
3404352f7f91STakashi Iwai 		break;
3405352f7f91STakashi Iwai 	default:
3406352f7f91STakashi Iwai 		return -EINVAL;
3407352f7f91STakashi Iwai 	}
3408352f7f91STakashi Iwai 	call_update_outputs(codec);
3409352f7f91STakashi Iwai 	return 1;
3410352f7f91STakashi Iwai }
3411352f7f91STakashi Iwai 
3412352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
3413352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3414352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
3415352f7f91STakashi Iwai 	.info = automute_mode_info,
3416352f7f91STakashi Iwai 	.get = automute_mode_get,
3417352f7f91STakashi Iwai 	.put = automute_mode_put,
3418352f7f91STakashi Iwai };
3419352f7f91STakashi Iwai 
3420352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
3421352f7f91STakashi Iwai {
3422352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3423352f7f91STakashi Iwai 
342412c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
3425352f7f91STakashi Iwai 		return -ENOMEM;
3426352f7f91STakashi Iwai 	return 0;
3427352f7f91STakashi Iwai }
3428352f7f91STakashi Iwai 
3429352f7f91STakashi Iwai /*
3430352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
3431352f7f91STakashi Iwai  * Set up appropriately if really supported
3432352f7f91STakashi Iwai  */
3433352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
3434352f7f91STakashi Iwai {
3435352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3436352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3437352f7f91STakashi Iwai 	int present = 0;
3438352f7f91STakashi Iwai 	int i, err;
3439352f7f91STakashi Iwai 
3440f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
3441f72706beSTakashi Iwai 		return 0;
3442f72706beSTakashi Iwai 
3443352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
3444352f7f91STakashi Iwai 		present++;
3445352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
3446352f7f91STakashi Iwai 		present++;
3447352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
3448352f7f91STakashi Iwai 		present++;
3449352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
3450352f7f91STakashi Iwai 		return 0;
3451352f7f91STakashi Iwai 
3452352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
3453352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
3454352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3455352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3456352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3457352f7f91STakashi Iwai 	}
3458352f7f91STakashi Iwai 
3459352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
3460352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
3461352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
3462352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
3463352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
3464352f7f91STakashi Iwai 	}
3465352f7f91STakashi Iwai 
3466352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
3467352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
3468352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
3469352f7f91STakashi Iwai 			continue;
3470352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
3471352f7f91STakashi Iwai 			    nid);
3472352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
34732e03e952STakashi Iwai 						    spec->hp_automute_hook ?
34742e03e952STakashi Iwai 						    spec->hp_automute_hook :
34755d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
3476352f7f91STakashi Iwai 		spec->detect_hp = 1;
3477352f7f91STakashi Iwai 	}
3478352f7f91STakashi Iwai 
3479352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
3480352f7f91STakashi Iwai 		if (cfg->speaker_outs)
3481352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
3482352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
3483352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
3484352f7f91STakashi Iwai 					continue;
3485352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
3486352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
3487352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
34882e03e952STakashi Iwai 								    spec->line_automute_hook ?
34892e03e952STakashi Iwai 								    spec->line_automute_hook :
34905d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
3491352f7f91STakashi Iwai 				spec->detect_lo = 1;
3492352f7f91STakashi Iwai 			}
3493352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
3494352f7f91STakashi Iwai 	}
3495352f7f91STakashi Iwai 
3496352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
3497352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
3498352f7f91STakashi Iwai 
3499352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
3500352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
3501352f7f91STakashi Iwai 
3502352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
3503352f7f91STakashi Iwai 		/* create a control for automute mode */
3504352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
3505352f7f91STakashi Iwai 		if (err < 0)
3506352f7f91STakashi Iwai 			return err;
3507352f7f91STakashi Iwai 	}
3508352f7f91STakashi Iwai 	return 0;
3509352f7f91STakashi Iwai }
3510352f7f91STakashi Iwai 
3511352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
3512352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
3513352f7f91STakashi Iwai {
3514352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3515352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3516352f7f91STakashi Iwai 	int i;
3517352f7f91STakashi Iwai 
3518352f7f91STakashi Iwai 	imux = &spec->input_mux;
3519352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
3520352f7f91STakashi Iwai 		spec->am_entry[i].idx =
3521352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
3522352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
3523352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
3524352f7f91STakashi Iwai 			return false; /* no corresponding imux */
3525352f7f91STakashi Iwai 	}
3526352f7f91STakashi Iwai 
3527352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
3528352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
3529352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
3530352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
3531352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
35322e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
35332e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
35345d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
3535352f7f91STakashi Iwai 	return true;
3536352f7f91STakashi Iwai }
3537352f7f91STakashi Iwai 
3538352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
3539352f7f91STakashi Iwai {
3540352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
3541352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
3542352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
3543352f7f91STakashi Iwai }
3544352f7f91STakashi Iwai 
3545352f7f91STakashi Iwai /*
3546352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
3547352f7f91STakashi Iwai  * Set up if really supported
3548352f7f91STakashi Iwai  */
3549352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
3550352f7f91STakashi Iwai {
3551352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3552352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3553352f7f91STakashi Iwai 	unsigned int types;
3554352f7f91STakashi Iwai 	int i, num_pins;
3555352f7f91STakashi Iwai 
3556d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
3557d12daf6fSTakashi Iwai 		return 0;
3558d12daf6fSTakashi Iwai 
3559352f7f91STakashi Iwai 	types = 0;
3560352f7f91STakashi Iwai 	num_pins = 0;
3561352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3562352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3563352f7f91STakashi Iwai 		unsigned int attr;
3564352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3565352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3566352f7f91STakashi Iwai 		if (types & (1 << attr))
3567352f7f91STakashi Iwai 			return 0; /* already occupied */
3568352f7f91STakashi Iwai 		switch (attr) {
3569352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3570352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3571352f7f91STakashi Iwai 				return 0; /* invalid type */
3572352f7f91STakashi Iwai 			break;
3573352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3574352f7f91STakashi Iwai 			return 0; /* invalid entry */
3575352f7f91STakashi Iwai 		default:
3576352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3577352f7f91STakashi Iwai 				return 0; /* invalid type */
3578352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3579352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3580352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3581352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3582352f7f91STakashi Iwai 				return 0; /* no unsol support */
3583352f7f91STakashi Iwai 			break;
3584352f7f91STakashi Iwai 		}
3585352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3586352f7f91STakashi Iwai 			return 0;
3587352f7f91STakashi Iwai 		types |= (1 << attr);
3588352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3589352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3590352f7f91STakashi Iwai 		num_pins++;
3591352f7f91STakashi Iwai 	}
3592352f7f91STakashi Iwai 
3593352f7f91STakashi Iwai 	if (num_pins < 2)
3594352f7f91STakashi Iwai 		return 0;
3595352f7f91STakashi Iwai 
3596352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3597352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3598352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3599352f7f91STakashi Iwai 	 */
3600352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3601352f7f91STakashi Iwai 	     compare_attr, NULL);
3602352f7f91STakashi Iwai 
3603352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3604352f7f91STakashi Iwai 		return 0;
3605352f7f91STakashi Iwai 
3606352f7f91STakashi Iwai 	spec->auto_mic = 1;
3607352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3608352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3609352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3610352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3611352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3612352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3613352f7f91STakashi Iwai 
3614352f7f91STakashi Iwai 	return 0;
3615352f7f91STakashi Iwai }
3616352f7f91STakashi Iwai 
3617352f7f91STakashi Iwai 
36189eb413e5STakashi Iwai /*
36199eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
36209eb413e5STakashi Iwai  *
36219eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3622352f7f91STakashi Iwai  * or a negative error code
3623352f7f91STakashi Iwai  */
3624352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
36259eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3626352f7f91STakashi Iwai {
3627352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3628352f7f91STakashi Iwai 	int err;
3629352f7f91STakashi Iwai 
36301c70a583STakashi Iwai 	parse_user_hints(codec);
36311c70a583STakashi Iwai 
36329eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
36339eb413e5STakashi Iwai 		spec->autocfg = *cfg;
36349eb413e5STakashi Iwai 		cfg = &spec->autocfg;
36359eb413e5STakashi Iwai 	}
36369eb413e5STakashi Iwai 
36376fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
36386fc4cb97SDavid Henningsson 
3639352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3640352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3641352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3642352f7f91STakashi Iwai 			spec->no_analog = 1;
3643352f7f91STakashi Iwai 			goto dig_only;
3644352f7f91STakashi Iwai 		}
3645352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3646352f7f91STakashi Iwai 	}
3647352f7f91STakashi Iwai 
3648352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3649352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3650352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3651352f7f91STakashi Iwai 		/* use HP as primary out */
3652352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3653352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3654352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3655352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3656352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3657352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3658352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3659352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3660352f7f91STakashi Iwai 	}
3661352f7f91STakashi Iwai 
3662352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3663352f7f91STakashi Iwai 	if (err < 0)
3664352f7f91STakashi Iwai 		return err;
3665352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3666352f7f91STakashi Iwai 	if (err < 0)
3667352f7f91STakashi Iwai 		return err;
3668352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3669352f7f91STakashi Iwai 	if (err < 0)
3670352f7f91STakashi Iwai 		return err;
3671352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3672352f7f91STakashi Iwai 	if (err < 0)
3673352f7f91STakashi Iwai 		return err;
3674352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3675352f7f91STakashi Iwai 	if (err < 0)
3676352f7f91STakashi Iwai 		return err;
367738cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
367838cf6f1aSTakashi Iwai 	if (err < 0)
367938cf6f1aSTakashi Iwai 		return err;
3680c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3681c30aa7b2STakashi Iwai 	if (err < 0)
3682c30aa7b2STakashi Iwai 		return err;
3683352f7f91STakashi Iwai 	err = create_shared_input(codec);
3684352f7f91STakashi Iwai 	if (err < 0)
3685352f7f91STakashi Iwai 		return err;
3686352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3687352f7f91STakashi Iwai 	if (err < 0)
3688352f7f91STakashi Iwai 		return err;
3689352f7f91STakashi Iwai 
3690a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
3691a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
3692a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
3693a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3694a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
3695a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3696a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3697a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
3698352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
3699352f7f91STakashi Iwai 					  spec->const_channel_count);
3700352f7f91STakashi Iwai 
3701352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3702352f7f91STakashi Iwai 	if (err < 0)
3703352f7f91STakashi Iwai 		return err;
3704352f7f91STakashi Iwai 
3705352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3706352f7f91STakashi Iwai 	if (err < 0)
3707352f7f91STakashi Iwai 		return err;
3708352f7f91STakashi Iwai 
3709352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3710352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3711352f7f91STakashi Iwai 		if (err < 0)
3712352f7f91STakashi Iwai 			return err;
3713352f7f91STakashi Iwai 	}
3714352f7f91STakashi Iwai 
3715352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3716352f7f91STakashi Iwai 	if (err < 0)
3717352f7f91STakashi Iwai 		return err;
3718352f7f91STakashi Iwai 
3719352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3720352f7f91STakashi Iwai 	if (err < 0)
3721352f7f91STakashi Iwai 		return err;
3722352f7f91STakashi Iwai 
3723978e77e7STakashi Iwai 	if (spec->add_out_jack_modes) {
3724978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3725978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
3726978e77e7STakashi Iwai 						    cfg->line_out_pins);
3727978e77e7STakashi Iwai 			if (err < 0)
3728978e77e7STakashi Iwai 				return err;
3729978e77e7STakashi Iwai 		}
3730978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
3731978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
3732978e77e7STakashi Iwai 						    cfg->hp_pins);
3733978e77e7STakashi Iwai 			if (err < 0)
3734978e77e7STakashi Iwai 				return err;
3735978e77e7STakashi Iwai 		}
3736978e77e7STakashi Iwai 	}
3737978e77e7STakashi Iwai 
3738352f7f91STakashi Iwai  dig_only:
3739352f7f91STakashi Iwai 	parse_digital(codec);
3740352f7f91STakashi Iwai 
3741352f7f91STakashi Iwai 	return 1;
3742352f7f91STakashi Iwai }
3743352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3744352f7f91STakashi Iwai 
3745352f7f91STakashi Iwai 
3746352f7f91STakashi Iwai /*
3747352f7f91STakashi Iwai  * Build control elements
3748352f7f91STakashi Iwai  */
3749352f7f91STakashi Iwai 
3750352f7f91STakashi Iwai /* slave controls for virtual master */
3751352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3752352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3753352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3754352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3755ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3756ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3757ee79c69aSTakashi Iwai 	"Headphone Side",
3758352f7f91STakashi Iwai 	NULL,
3759352f7f91STakashi Iwai };
3760352f7f91STakashi Iwai 
3761352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3762352f7f91STakashi Iwai {
3763352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3764352f7f91STakashi Iwai 	int err;
3765352f7f91STakashi Iwai 
376636502d02STakashi Iwai 	if (spec->kctls.used) {
3767352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3768352f7f91STakashi Iwai 		if (err < 0)
3769352f7f91STakashi Iwai 			return err;
377036502d02STakashi Iwai 	}
3771352f7f91STakashi Iwai 
3772352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3773352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3774352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3775352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3776352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3777352f7f91STakashi Iwai 		if (err < 0)
3778352f7f91STakashi Iwai 			return err;
3779352f7f91STakashi Iwai 		if (!spec->no_analog) {
3780352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3781352f7f91STakashi Iwai 							    &spec->multiout);
3782352f7f91STakashi Iwai 			if (err < 0)
3783352f7f91STakashi Iwai 				return err;
3784352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3785352f7f91STakashi Iwai 		}
3786352f7f91STakashi Iwai 	}
3787352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3788352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3789352f7f91STakashi Iwai 		if (err < 0)
3790352f7f91STakashi Iwai 			return err;
3791352f7f91STakashi Iwai 	}
3792352f7f91STakashi Iwai 
3793352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3794352f7f91STakashi Iwai 	if (!spec->no_analog &&
3795352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3796352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
37977a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
3798352f7f91STakashi Iwai 					  "Playback Volume");
3799352f7f91STakashi Iwai 		if (err < 0)
3800352f7f91STakashi Iwai 			return err;
3801352f7f91STakashi Iwai 	}
3802352f7f91STakashi Iwai 	if (!spec->no_analog &&
3803352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3804352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3805352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3806352f7f91STakashi Iwai 					    "Playback Switch",
3807352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3808352f7f91STakashi Iwai 		if (err < 0)
3809352f7f91STakashi Iwai 			return err;
3810352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3811fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3812fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3813352f7f91STakashi Iwai 	}
3814352f7f91STakashi Iwai 
3815352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3816352f7f91STakashi Iwai 
3817352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3818352f7f91STakashi Iwai 		int err;
3819352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3820352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3821352f7f91STakashi Iwai 		if (err < 0)
3822352f7f91STakashi Iwai 			return err;
3823352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3824352f7f91STakashi Iwai 		if (err < 0)
3825352f7f91STakashi Iwai 			return err;
3826352f7f91STakashi Iwai 	}
3827352f7f91STakashi Iwai 
3828352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3829352f7f91STakashi Iwai 	if (err < 0)
3830352f7f91STakashi Iwai 		return err;
3831352f7f91STakashi Iwai 
3832352f7f91STakashi Iwai 	return 0;
3833352f7f91STakashi Iwai }
3834352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3835352f7f91STakashi Iwai 
3836352f7f91STakashi Iwai 
3837352f7f91STakashi Iwai /*
3838352f7f91STakashi Iwai  * PCM definitions
3839352f7f91STakashi Iwai  */
3840352f7f91STakashi Iwai 
3841e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
3842e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
3843e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
3844e6b85f3cSTakashi Iwai 				   int action)
3845e6b85f3cSTakashi Iwai {
3846e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3847e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
3848e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
3849e6b85f3cSTakashi Iwai }
3850e6b85f3cSTakashi Iwai 
3851ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
3852ac2e8736STakashi Iwai 				  struct hda_codec *codec,
3853ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
3854ac2e8736STakashi Iwai 				  int action)
3855ac2e8736STakashi Iwai {
3856ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3857ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
3858ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
3859ac2e8736STakashi Iwai }
3860ac2e8736STakashi Iwai 
3861352f7f91STakashi Iwai /*
3862352f7f91STakashi Iwai  * Analog playback callbacks
3863352f7f91STakashi Iwai  */
3864352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3865352f7f91STakashi Iwai 			     struct hda_codec *codec,
3866352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3867352f7f91STakashi Iwai {
3868352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
386938cf6f1aSTakashi Iwai 	int err;
387038cf6f1aSTakashi Iwai 
387138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
387238cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
387338cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3874352f7f91STakashi Iwai 					     hinfo);
3875e6b85f3cSTakashi Iwai 	if (!err) {
387638cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
3877e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3878e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
3879e6b85f3cSTakashi Iwai 	}
388038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
388138cf6f1aSTakashi Iwai 	return err;
3882352f7f91STakashi Iwai }
3883352f7f91STakashi Iwai 
3884352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
388597ec558aSTakashi Iwai 				struct hda_codec *codec,
388697ec558aSTakashi Iwai 				unsigned int stream_tag,
388797ec558aSTakashi Iwai 				unsigned int format,
388897ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
388997ec558aSTakashi Iwai {
3890352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3891e6b85f3cSTakashi Iwai 	int err;
3892e6b85f3cSTakashi Iwai 
3893e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3894352f7f91STakashi Iwai 					       stream_tag, format, substream);
3895e6b85f3cSTakashi Iwai 	if (!err)
3896e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3897e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
3898e6b85f3cSTakashi Iwai 	return err;
3899352f7f91STakashi Iwai }
390097ec558aSTakashi Iwai 
3901352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3902352f7f91STakashi Iwai 				struct hda_codec *codec,
3903352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3904352f7f91STakashi Iwai {
3905352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3906e6b85f3cSTakashi Iwai 	int err;
3907e6b85f3cSTakashi Iwai 
3908e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3909e6b85f3cSTakashi Iwai 	if (!err)
3910e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3911e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
3912e6b85f3cSTakashi Iwai 	return err;
3913352f7f91STakashi Iwai }
3914352f7f91STakashi Iwai 
391538cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
391638cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
391738cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
391838cf6f1aSTakashi Iwai {
391938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
392038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
392138cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
3922e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3923e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
392438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
392538cf6f1aSTakashi Iwai 	return 0;
392638cf6f1aSTakashi Iwai }
392738cf6f1aSTakashi Iwai 
3928ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
3929ac2e8736STakashi Iwai 			    struct hda_codec *codec,
3930ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
3931ac2e8736STakashi Iwai {
3932ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
3933ac2e8736STakashi Iwai 	return 0;
3934ac2e8736STakashi Iwai }
3935ac2e8736STakashi Iwai 
3936ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3937ac2e8736STakashi Iwai 			       struct hda_codec *codec,
3938ac2e8736STakashi Iwai 			       unsigned int stream_tag,
3939ac2e8736STakashi Iwai 			       unsigned int format,
3940ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
3941ac2e8736STakashi Iwai {
3942ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3943ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
3944ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
3945ac2e8736STakashi Iwai 	return 0;
3946ac2e8736STakashi Iwai }
3947ac2e8736STakashi Iwai 
3948ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3949ac2e8736STakashi Iwai 			       struct hda_codec *codec,
3950ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
3951ac2e8736STakashi Iwai {
3952ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
3953ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
3954ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
3955ac2e8736STakashi Iwai 	return 0;
3956ac2e8736STakashi Iwai }
3957ac2e8736STakashi Iwai 
3958ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
3959ac2e8736STakashi Iwai 			     struct hda_codec *codec,
3960ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
3961ac2e8736STakashi Iwai {
3962ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
3963ac2e8736STakashi Iwai 	return 0;
3964ac2e8736STakashi Iwai }
3965ac2e8736STakashi Iwai 
396638cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
396738cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
396838cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
396938cf6f1aSTakashi Iwai {
397038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
397138cf6f1aSTakashi Iwai 	int err = 0;
397238cf6f1aSTakashi Iwai 
397338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
397438cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
397538cf6f1aSTakashi Iwai 		err = -EBUSY;
397638cf6f1aSTakashi Iwai 	else
397738cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
3978e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3979e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
398038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
398138cf6f1aSTakashi Iwai 	return err;
398238cf6f1aSTakashi Iwai }
398338cf6f1aSTakashi Iwai 
398438cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
398538cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
398638cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
398738cf6f1aSTakashi Iwai {
398838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
398938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
399038cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
3991e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3992e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
399338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
399438cf6f1aSTakashi Iwai 	return 0;
399538cf6f1aSTakashi Iwai }
399638cf6f1aSTakashi Iwai 
3997e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3998e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
3999e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4000e6b85f3cSTakashi Iwai 				    unsigned int format,
4001e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4002e6b85f3cSTakashi Iwai {
4003e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4004e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4005e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4006e6b85f3cSTakashi Iwai 	return 0;
4007e6b85f3cSTakashi Iwai }
4008e6b85f3cSTakashi Iwai 
4009e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4010e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4011e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4012e6b85f3cSTakashi Iwai {
4013e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4014e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4015e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4016e6b85f3cSTakashi Iwai 	return 0;
4017e6b85f3cSTakashi Iwai }
4018e6b85f3cSTakashi Iwai 
4019352f7f91STakashi Iwai /*
4020352f7f91STakashi Iwai  * Digital out
4021352f7f91STakashi Iwai  */
4022352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4023352f7f91STakashi Iwai 				 struct hda_codec *codec,
4024352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4025352f7f91STakashi Iwai {
4026352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4027352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4028352f7f91STakashi Iwai }
4029352f7f91STakashi Iwai 
4030352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4031352f7f91STakashi Iwai 				    struct hda_codec *codec,
4032352f7f91STakashi Iwai 				    unsigned int stream_tag,
4033352f7f91STakashi Iwai 				    unsigned int format,
4034352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4035352f7f91STakashi Iwai {
4036352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4037352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4038352f7f91STakashi Iwai 					     stream_tag, format, substream);
4039352f7f91STakashi Iwai }
4040352f7f91STakashi Iwai 
4041352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4042352f7f91STakashi Iwai 				    struct hda_codec *codec,
4043352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4044352f7f91STakashi Iwai {
4045352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4046352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4047352f7f91STakashi Iwai }
4048352f7f91STakashi Iwai 
4049352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4050352f7f91STakashi Iwai 				  struct hda_codec *codec,
4051352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4052352f7f91STakashi Iwai {
4053352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4054352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4055352f7f91STakashi Iwai }
4056352f7f91STakashi Iwai 
4057352f7f91STakashi Iwai /*
4058352f7f91STakashi Iwai  * Analog capture
4059352f7f91STakashi Iwai  */
4060ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4061ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4062ac2e8736STakashi Iwai 
4063352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4064352f7f91STakashi Iwai 				   struct hda_codec *codec,
4065352f7f91STakashi Iwai 				   unsigned int stream_tag,
4066352f7f91STakashi Iwai 				   unsigned int format,
4067352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4068352f7f91STakashi Iwai {
4069352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4070352f7f91STakashi Iwai 
4071352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
407297ec558aSTakashi Iwai 				   stream_tag, 0, format);
4073ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4074ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
407597ec558aSTakashi Iwai 	return 0;
407697ec558aSTakashi Iwai }
407797ec558aSTakashi Iwai 
4078352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
407997ec558aSTakashi Iwai 				   struct hda_codec *codec,
408097ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
408197ec558aSTakashi Iwai {
4082352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
408397ec558aSTakashi Iwai 
4084352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4085352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4086ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4087ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
408897ec558aSTakashi Iwai 	return 0;
408997ec558aSTakashi Iwai }
409097ec558aSTakashi Iwai 
4091352f7f91STakashi Iwai /*
4092352f7f91STakashi Iwai  */
4093352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4094352f7f91STakashi Iwai 	.substreams = 1,
4095352f7f91STakashi Iwai 	.channels_min = 2,
4096352f7f91STakashi Iwai 	.channels_max = 8,
4097352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4098352f7f91STakashi Iwai 	.ops = {
4099352f7f91STakashi Iwai 		.open = playback_pcm_open,
410038cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4101352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4102352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4103352f7f91STakashi Iwai 	},
4104352f7f91STakashi Iwai };
4105352f7f91STakashi Iwai 
4106352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4107352f7f91STakashi Iwai 	.substreams = 1,
4108352f7f91STakashi Iwai 	.channels_min = 2,
4109352f7f91STakashi Iwai 	.channels_max = 2,
4110352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4111ac2e8736STakashi Iwai 	.ops = {
4112ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4113ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4114ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4115ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4116ac2e8736STakashi Iwai 	},
4117352f7f91STakashi Iwai };
4118352f7f91STakashi Iwai 
4119352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4120352f7f91STakashi Iwai 	.substreams = 1,
4121352f7f91STakashi Iwai 	.channels_min = 2,
4122352f7f91STakashi Iwai 	.channels_max = 2,
4123352f7f91STakashi Iwai 	/* NID is set in build_pcms */
412438cf6f1aSTakashi Iwai 	.ops = {
412538cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4126e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4127e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4128e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
412938cf6f1aSTakashi Iwai 	},
4130352f7f91STakashi Iwai };
4131352f7f91STakashi Iwai 
4132352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4133352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4134352f7f91STakashi Iwai 	.channels_min = 2,
4135352f7f91STakashi Iwai 	.channels_max = 2,
4136352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4137352f7f91STakashi Iwai 	.ops = {
4138ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4139ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4140352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4141352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4142352f7f91STakashi Iwai 	},
4143352f7f91STakashi Iwai };
4144352f7f91STakashi Iwai 
4145352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4146352f7f91STakashi Iwai 	.substreams = 1,
4147352f7f91STakashi Iwai 	.channels_min = 2,
4148352f7f91STakashi Iwai 	.channels_max = 2,
4149352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4150352f7f91STakashi Iwai 	.ops = {
4151352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4152352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4153352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4154352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4155352f7f91STakashi Iwai 	},
4156352f7f91STakashi Iwai };
4157352f7f91STakashi Iwai 
4158352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4159352f7f91STakashi Iwai 	.substreams = 1,
4160352f7f91STakashi Iwai 	.channels_min = 2,
4161352f7f91STakashi Iwai 	.channels_max = 2,
4162352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4163352f7f91STakashi Iwai };
4164352f7f91STakashi Iwai 
4165352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4166352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4167352f7f91STakashi Iwai 	.substreams = 0,
4168352f7f91STakashi Iwai 	.channels_min = 0,
4169352f7f91STakashi Iwai 	.channels_max = 0,
4170352f7f91STakashi Iwai };
4171352f7f91STakashi Iwai 
4172352f7f91STakashi Iwai /*
4173352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4174352f7f91STakashi Iwai  */
4175352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
41761da177e4SLinus Torvalds {
4177352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4178352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
41791da177e4SLinus Torvalds 
4180352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4181352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4182352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4183352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4184352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4185352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4186352f7f91STakashi Iwai 					   spec->cur_adc_format);
4187352f7f91STakashi Iwai 		return true;
4188352f7f91STakashi Iwai 	}
4189352f7f91STakashi Iwai 	return false;
4190352f7f91STakashi Iwai }
4191352f7f91STakashi Iwai 
4192352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4193352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4194352f7f91STakashi Iwai 				       struct hda_codec *codec,
4195352f7f91STakashi Iwai 				       unsigned int stream_tag,
4196352f7f91STakashi Iwai 				       unsigned int format,
4197352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4198352f7f91STakashi Iwai {
4199352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4200352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4201352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4202352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4203352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
42041da177e4SLinus Torvalds 	return 0;
42051da177e4SLinus Torvalds }
42061da177e4SLinus Torvalds 
4207352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4208352f7f91STakashi Iwai 				       struct hda_codec *codec,
4209352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4210352f7f91STakashi Iwai {
4211352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4212352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4213352f7f91STakashi Iwai 	spec->cur_adc = 0;
4214352f7f91STakashi Iwai 	return 0;
4215352f7f91STakashi Iwai }
4216352f7f91STakashi Iwai 
4217352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4218352f7f91STakashi Iwai 	.substreams = 1,
4219352f7f91STakashi Iwai 	.channels_min = 2,
4220352f7f91STakashi Iwai 	.channels_max = 2,
4221352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4222352f7f91STakashi Iwai 	.ops = {
4223352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4224352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4225352f7f91STakashi Iwai 	},
4226352f7f91STakashi Iwai };
4227352f7f91STakashi Iwai 
4228f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4229f873e536STakashi Iwai 				 const char *chip_name)
4230f873e536STakashi Iwai {
4231f873e536STakashi Iwai 	char *p;
4232f873e536STakashi Iwai 
4233f873e536STakashi Iwai 	if (*str)
4234f873e536STakashi Iwai 		return;
4235f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4236f873e536STakashi Iwai 
4237f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4238f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4239f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4240f873e536STakashi Iwai 			*p = 0;
4241f873e536STakashi Iwai 			break;
4242f873e536STakashi Iwai 		}
4243f873e536STakashi Iwai 	}
4244f873e536STakashi Iwai 	strlcat(str, sfx, len);
4245f873e536STakashi Iwai }
4246f873e536STakashi Iwai 
4247352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4248352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4249352f7f91STakashi Iwai {
4250352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4251352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4252352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4253352f7f91STakashi Iwai 	bool have_multi_adcs;
4254352f7f91STakashi Iwai 
42551da177e4SLinus Torvalds 	codec->num_pcms = 1;
42561da177e4SLinus Torvalds 	codec->pcm_info = info;
42571da177e4SLinus Torvalds 
4258352f7f91STakashi Iwai 	if (spec->no_analog)
4259352f7f91STakashi Iwai 		goto skip_analog;
4260352f7f91STakashi Iwai 
4261f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
4262f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
4263f873e536STakashi Iwai 			     " Analog", codec->chip_name);
4264352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
4265352f7f91STakashi Iwai 
4266352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
4267352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
4268352f7f91STakashi Iwai 		if (!p)
4269352f7f91STakashi Iwai 			p = &pcm_analog_playback;
4270352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4271352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4272352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
4273352f7f91STakashi Iwai 			spec->multiout.max_channels;
4274352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
4275352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
4276352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
4277352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
4278352f7f91STakashi Iwai 	}
4279352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
4280352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
4281352f7f91STakashi Iwai 		if (!p) {
4282352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
4283352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
4284352f7f91STakashi Iwai 			else
4285352f7f91STakashi Iwai 				p = &pcm_analog_capture;
4286352f7f91STakashi Iwai 		}
4287352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4288352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4289352f7f91STakashi Iwai 	}
4290352f7f91STakashi Iwai 
4291352f7f91STakashi Iwai  skip_analog:
4292352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
4293352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4294f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
4295352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
4296f873e536STakashi Iwai 				     " Digital", codec->chip_name);
4297352f7f91STakashi Iwai 		codec->num_pcms = 2;
4298352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4299352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
4300352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
4301352f7f91STakashi Iwai 		if (spec->dig_out_type)
4302352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
4303352f7f91STakashi Iwai 		else
4304352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
4305352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
4306352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
4307352f7f91STakashi Iwai 			if (!p)
4308352f7f91STakashi Iwai 				p = &pcm_digital_playback;
4309352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4310352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
4311352f7f91STakashi Iwai 		}
4312352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
4313352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
4314352f7f91STakashi Iwai 			if (!p)
4315352f7f91STakashi Iwai 				p = &pcm_digital_capture;
4316352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4317352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4318352f7f91STakashi Iwai 		}
4319352f7f91STakashi Iwai 	}
4320352f7f91STakashi Iwai 
4321352f7f91STakashi Iwai 	if (spec->no_analog)
4322352f7f91STakashi Iwai 		return 0;
4323352f7f91STakashi Iwai 
4324352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
4325352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
4326352f7f91STakashi Iwai 	 */
4327352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
4328352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
4329352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
4330352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
4331352f7f91STakashi Iwai 		codec->num_pcms = 3;
4332352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
4333352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
4334352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
4335352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
4336352f7f91STakashi Iwai 			if (!p)
4337352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
4338352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4339352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4340352f7f91STakashi Iwai 				spec->alt_dac_nid;
4341352f7f91STakashi Iwai 		} else {
4342352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4343352f7f91STakashi Iwai 				pcm_null_stream;
4344352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4345352f7f91STakashi Iwai 		}
4346352f7f91STakashi Iwai 		if (have_multi_adcs) {
4347352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
4348352f7f91STakashi Iwai 			if (!p)
4349352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
4350352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4351352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4352352f7f91STakashi Iwai 				spec->adc_nids[1];
4353352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4354352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
4355352f7f91STakashi Iwai 		} else {
4356352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4357352f7f91STakashi Iwai 				pcm_null_stream;
4358352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4359352f7f91STakashi Iwai 		}
43601da177e4SLinus Torvalds 	}
43611da177e4SLinus Torvalds 
43621da177e4SLinus Torvalds 	return 0;
43631da177e4SLinus Torvalds }
4364352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
4365352f7f91STakashi Iwai 
4366352f7f91STakashi Iwai 
4367352f7f91STakashi Iwai /*
4368352f7f91STakashi Iwai  * Standard auto-parser initializations
4369352f7f91STakashi Iwai  */
4370352f7f91STakashi Iwai 
4371d4156930STakashi Iwai /* configure the given path as a proper output */
43722c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
4373352f7f91STakashi Iwai {
4374352f7f91STakashi Iwai 	struct nid_path *path;
4375d4156930STakashi Iwai 	hda_nid_t pin;
4376352f7f91STakashi Iwai 
4377196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
4378d4156930STakashi Iwai 	if (!path || !path->depth)
4379352f7f91STakashi Iwai 		return;
4380d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
43812c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
4382e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
4383e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
4384352f7f91STakashi Iwai }
4385352f7f91STakashi Iwai 
4386352f7f91STakashi Iwai /* initialize primary output paths */
4387352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
4388352f7f91STakashi Iwai {
4389352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4390352f7f91STakashi Iwai 	int i;
4391352f7f91STakashi Iwai 
4392d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
43932c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
4394352f7f91STakashi Iwai }
4395352f7f91STakashi Iwai 
4396db23fd19STakashi Iwai 
43972c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
4398352f7f91STakashi Iwai {
4399352f7f91STakashi Iwai 	int i;
4400352f7f91STakashi Iwai 
4401d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
44022c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
4403352f7f91STakashi Iwai }
4404db23fd19STakashi Iwai 
4405db23fd19STakashi Iwai /* initialize hp and speaker paths */
4406db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
4407db23fd19STakashi Iwai {
4408db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4409db23fd19STakashi Iwai 
4410db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
44112c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
4412db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
4413db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
44142c12c30dSTakashi Iwai 				 spec->speaker_paths);
4415352f7f91STakashi Iwai }
4416352f7f91STakashi Iwai 
4417352f7f91STakashi Iwai /* initialize multi-io paths */
4418352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
4419352f7f91STakashi Iwai {
4420352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4421352f7f91STakashi Iwai 	int i;
4422352f7f91STakashi Iwai 
4423352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
4424352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
4425352f7f91STakashi Iwai 		struct nid_path *path;
4426196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
4427352f7f91STakashi Iwai 		if (!path)
4428352f7f91STakashi Iwai 			continue;
4429352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
4430352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
44312c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
4432352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
4433352f7f91STakashi Iwai 	}
4434352f7f91STakashi Iwai }
4435352f7f91STakashi Iwai 
4436352f7f91STakashi Iwai /* set up input pins and loopback paths */
4437352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
4438352f7f91STakashi Iwai {
4439352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4440352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4441352f7f91STakashi Iwai 	int i;
4442352f7f91STakashi Iwai 
4443352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4444352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4445352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
44462c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
4447352f7f91STakashi Iwai 
4448352f7f91STakashi Iwai 		/* init loopback inputs */
4449352f7f91STakashi Iwai 		if (spec->mixer_nid) {
4450352f7f91STakashi Iwai 			struct nid_path *path;
4451196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
4452352f7f91STakashi Iwai 			if (path)
4453352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
4454352f7f91STakashi Iwai 						      path->active, false);
4455352f7f91STakashi Iwai 		}
4456352f7f91STakashi Iwai 	}
4457352f7f91STakashi Iwai }
4458352f7f91STakashi Iwai 
4459352f7f91STakashi Iwai /* initialize ADC paths */
4460352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
4461352f7f91STakashi Iwai {
4462352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4463352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
4464352f7f91STakashi Iwai 	struct nid_path *path;
4465352f7f91STakashi Iwai 	int i, c, nums;
4466352f7f91STakashi Iwai 
4467352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4468352f7f91STakashi Iwai 		nums = 1;
4469352f7f91STakashi Iwai 	else
4470352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
4471352f7f91STakashi Iwai 
4472352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
4473352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
4474c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
4475352f7f91STakashi Iwai 			if (path) {
4476352f7f91STakashi Iwai 				bool active = path->active;
4477352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
4478352f7f91STakashi Iwai 					active = true;
4479352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
4480352f7f91STakashi Iwai 			}
4481352f7f91STakashi Iwai 		}
4482352f7f91STakashi Iwai 	}
4483352f7f91STakashi Iwai 
4484352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
4485352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
4486352f7f91STakashi Iwai 
4487352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
4488352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
4489352f7f91STakashi Iwai }
4490352f7f91STakashi Iwai 
4491352f7f91STakashi Iwai /* set right pin controls for digital I/O */
4492352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
4493352f7f91STakashi Iwai {
4494352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4495352f7f91STakashi Iwai 	int i;
4496352f7f91STakashi Iwai 	hda_nid_t pin;
4497352f7f91STakashi Iwai 
4498d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
44992c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
4500352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
45012430d7b7STakashi Iwai 	if (pin) {
45022430d7b7STakashi Iwai 		struct nid_path *path;
45032c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
45042430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
45052430d7b7STakashi Iwai 		if (path)
45062430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
45072430d7b7STakashi Iwai 	}
4508352f7f91STakashi Iwai }
4509352f7f91STakashi Iwai 
4510973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
4511973e4972STakashi Iwai  * invalid unsol tags by some reason
4512973e4972STakashi Iwai  */
4513973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
4514973e4972STakashi Iwai {
4515973e4972STakashi Iwai 	int i;
4516973e4972STakashi Iwai 
4517973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
4518973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
4519973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
4520973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
4521973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
4522973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
4523973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
4524973e4972STakashi Iwai 	}
4525973e4972STakashi Iwai }
4526973e4972STakashi Iwai 
45275187ac16STakashi Iwai /*
45285187ac16STakashi Iwai  * initialize the generic spec;
45295187ac16STakashi Iwai  * this can be put as patch_ops.init function
45305187ac16STakashi Iwai  */
4531352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
4532352f7f91STakashi Iwai {
4533352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4534352f7f91STakashi Iwai 
4535352f7f91STakashi Iwai 	if (spec->init_hook)
4536352f7f91STakashi Iwai 		spec->init_hook(codec);
4537352f7f91STakashi Iwai 
4538352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
4539352f7f91STakashi Iwai 
45403bbcd274STakashi Iwai 	codec->cached_write = 1;
45413bbcd274STakashi Iwai 
4542352f7f91STakashi Iwai 	init_multi_out(codec);
4543352f7f91STakashi Iwai 	init_extra_out(codec);
4544352f7f91STakashi Iwai 	init_multi_io(codec);
4545352f7f91STakashi Iwai 	init_analog_input(codec);
4546352f7f91STakashi Iwai 	init_input_src(codec);
4547352f7f91STakashi Iwai 	init_digital(codec);
4548352f7f91STakashi Iwai 
4549973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
4550973e4972STakashi Iwai 
4551352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
4552a5cc2509STakashi Iwai 	update_automute_all(codec);
4553352f7f91STakashi Iwai 
45543bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
45553bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
45563bbcd274STakashi Iwai 
4557352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
4558352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4559352f7f91STakashi Iwai 
4560352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
4561352f7f91STakashi Iwai 	return 0;
4562352f7f91STakashi Iwai }
4563fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
4564fce52a3bSTakashi Iwai 
45655187ac16STakashi Iwai /*
45665187ac16STakashi Iwai  * free the generic spec;
45675187ac16STakashi Iwai  * this can be put as patch_ops.free function
45685187ac16STakashi Iwai  */
4569fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
4570fce52a3bSTakashi Iwai {
4571fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
4572fce52a3bSTakashi Iwai 	kfree(codec->spec);
4573fce52a3bSTakashi Iwai 	codec->spec = NULL;
4574fce52a3bSTakashi Iwai }
4575fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
4576fce52a3bSTakashi Iwai 
4577fce52a3bSTakashi Iwai #ifdef CONFIG_PM
45785187ac16STakashi Iwai /*
45795187ac16STakashi Iwai  * check the loopback power save state;
45805187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
45815187ac16STakashi Iwai  */
4582fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4583fce52a3bSTakashi Iwai {
4584fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4585fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4586fce52a3bSTakashi Iwai }
4587fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
4588fce52a3bSTakashi Iwai #endif
4589352f7f91STakashi Iwai 
4590352f7f91STakashi Iwai 
4591352f7f91STakashi Iwai /*
4592352f7f91STakashi Iwai  * the generic codec support
4593352f7f91STakashi Iwai  */
45941da177e4SLinus Torvalds 
4595352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
4596352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
4597352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
4598352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
4599fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
4600352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
460183012a7cSTakashi Iwai #ifdef CONFIG_PM
4602fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
4603cb53c626STakashi Iwai #endif
46041da177e4SLinus Torvalds };
46051da177e4SLinus Torvalds 
46061da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
46071da177e4SLinus Torvalds {
4608352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
46091da177e4SLinus Torvalds 	int err;
46101da177e4SLinus Torvalds 
4611e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4612352f7f91STakashi Iwai 	if (!spec)
46131da177e4SLinus Torvalds 		return -ENOMEM;
4614352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
46151da177e4SLinus Torvalds 	codec->spec = spec;
46161da177e4SLinus Torvalds 
46179eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
46189eb413e5STakashi Iwai 	if (err < 0)
46199eb413e5STakashi Iwai 		return err;
46209eb413e5STakashi Iwai 
46219eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
4622352f7f91STakashi Iwai 	if (err < 0)
46231da177e4SLinus Torvalds 		goto error;
46241da177e4SLinus Torvalds 
46251da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
46261da177e4SLinus Torvalds 	return 0;
46271da177e4SLinus Torvalds 
46281da177e4SLinus Torvalds error:
4629fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
46301da177e4SLinus Torvalds 	return err;
46311da177e4SLinus Torvalds }
4632fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
4633