xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 1c70a583)
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>
291da177e4SLinus Torvalds #include <sound/core.h>
30352f7f91STakashi Iwai #include <sound/jack.h>
311da177e4SLinus Torvalds #include "hda_codec.h"
321da177e4SLinus Torvalds #include "hda_local.h"
33352f7f91STakashi Iwai #include "hda_auto_parser.h"
34352f7f91STakashi Iwai #include "hda_jack.h"
35352f7f91STakashi Iwai #include "hda_generic.h"
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 
38352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
39352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
401da177e4SLinus Torvalds {
41352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
42352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
4338cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
44352f7f91STakashi Iwai 	return 0;
45352f7f91STakashi Iwai }
46352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
471da177e4SLinus Torvalds 
4812c93df6STakashi Iwai struct snd_kcontrol_new *
4912c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
50352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
51352f7f91STakashi Iwai {
52352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
53352f7f91STakashi Iwai 	if (!knew)
54352f7f91STakashi Iwai 		return NULL;
55352f7f91STakashi Iwai 	*knew = *temp;
56352f7f91STakashi Iwai 	if (name)
57352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
58352f7f91STakashi Iwai 	else if (knew->name)
59352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
60352f7f91STakashi Iwai 	if (!knew->name)
61352f7f91STakashi Iwai 		return NULL;
62352f7f91STakashi Iwai 	return knew;
63352f7f91STakashi Iwai }
6412c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
65352f7f91STakashi Iwai 
66352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
67352f7f91STakashi Iwai {
68352f7f91STakashi Iwai 	if (spec->kctls.list) {
69352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
70352f7f91STakashi Iwai 		int i;
71352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
72352f7f91STakashi Iwai 			kfree(kctl[i].name);
73352f7f91STakashi Iwai 	}
74352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
75352f7f91STakashi Iwai }
76352f7f91STakashi Iwai 
77352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
78352f7f91STakashi Iwai {
791da177e4SLinus Torvalds 	if (!spec)
801da177e4SLinus Torvalds 		return;
81352f7f91STakashi Iwai 	free_kctls(spec);
82352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
831da177e4SLinus Torvalds }
84352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds /*
87*1c70a583STakashi Iwai  * store user hints
88*1c70a583STakashi Iwai  */
89*1c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
90*1c70a583STakashi Iwai {
91*1c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
92*1c70a583STakashi Iwai 	int val;
93*1c70a583STakashi Iwai 
94*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
95*1c70a583STakashi Iwai 	if (val >= 0)
96*1c70a583STakashi Iwai 		codec->no_jack_detect = !val;
97*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
98*1c70a583STakashi Iwai 	if (val >= 0)
99*1c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
100*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
101*1c70a583STakashi Iwai 	if (val >= 0)
102*1c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
103*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
104*1c70a583STakashi Iwai 	if (val >= 0)
105*1c70a583STakashi Iwai 		codec->inv_eapd = !!val;
106*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
107*1c70a583STakashi Iwai 	if (val >= 0)
108*1c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
109*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
110*1c70a583STakashi Iwai 	if (val >= 0)
111*1c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
112*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
113*1c70a583STakashi Iwai 	if (val >= 0)
114*1c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
115*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
116*1c70a583STakashi Iwai 	if (val >= 0)
117*1c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
118*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
119*1c70a583STakashi Iwai 	if (val >= 0)
120*1c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
121*1c70a583STakashi Iwai 
122*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
123*1c70a583STakashi Iwai 	if (val >= 0)
124*1c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
125*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
126*1c70a583STakashi Iwai 	if (val >= 0)
127*1c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
128*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
129*1c70a583STakashi Iwai 	if (val >= 0)
130*1c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
131*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
132*1c70a583STakashi Iwai 	if (val >= 0)
133*1c70a583STakashi Iwai 		spec->no_primary_hp = !val;
134*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
135*1c70a583STakashi Iwai 	if (val >= 0)
136*1c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
137*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
138*1c70a583STakashi Iwai 	if (val >= 0)
139*1c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
140*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
141*1c70a583STakashi Iwai 	if (val >= 0)
142*1c70a583STakashi Iwai 		spec->indep_hp = !!val;
143*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
144*1c70a583STakashi Iwai 	if (val >= 0)
145*1c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
146*1c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
147*1c70a583STakashi Iwai 	if (val >= 0)
148*1c70a583STakashi Iwai 		spec->add_out_jack_modes = !!val;
149*1c70a583STakashi Iwai 
150*1c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
151*1c70a583STakashi Iwai 		spec->mixer_nid = val;
152*1c70a583STakashi Iwai }
153*1c70a583STakashi Iwai 
154*1c70a583STakashi Iwai /*
1552c12c30dSTakashi Iwai  * pin control value accesses
1562c12c30dSTakashi Iwai  */
1572c12c30dSTakashi Iwai 
1582c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
1592c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
1602c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
1612c12c30dSTakashi Iwai 
1622c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
1632c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
1642c12c30dSTakashi Iwai {
1652c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
1662c12c30dSTakashi Iwai }
1672c12c30dSTakashi Iwai 
1682c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
1692c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
1702c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
1712c12c30dSTakashi Iwai {
1722c12c30dSTakashi Iwai 	if (!pin)
1732c12c30dSTakashi Iwai 		return;
1742c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
1752c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
1762c12c30dSTakashi Iwai 	if (do_write)
1772c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
1782c12c30dSTakashi Iwai }
1792c12c30dSTakashi Iwai 
1802c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
1812c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
1822c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
1832c12c30dSTakashi Iwai {
1842c12c30dSTakashi Iwai 	int i;
1852c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
1862c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
1872c12c30dSTakashi Iwai }
1882c12c30dSTakashi Iwai 
1892c12c30dSTakashi Iwai /*
190352f7f91STakashi Iwai  * parsing paths
1911da177e4SLinus Torvalds  */
1921da177e4SLinus Torvalds 
1933ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
1943ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
1953ca529d3STakashi Iwai {
1963ca529d3STakashi Iwai 	int i;
1973ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
1983ca529d3STakashi Iwai 		if (list[i] == nid)
1993ca529d3STakashi Iwai 			return i;
2003ca529d3STakashi Iwai 	return -1;
2013ca529d3STakashi Iwai }
2023ca529d3STakashi Iwai 
2033ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2043ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2053ca529d3STakashi Iwai {
2063ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2073ca529d3STakashi Iwai }
2083ca529d3STakashi Iwai 
209f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
210f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2113ca529d3STakashi Iwai 				     int anchor_nid)
2121da177e4SLinus Torvalds {
213352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
214352f7f91STakashi Iwai 	int i;
2151da177e4SLinus Torvalds 
216352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
217352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
218352f7f91STakashi Iwai 		if (path->depth <= 0)
219352f7f91STakashi Iwai 			continue;
220352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
221f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2223ca529d3STakashi Iwai 			if (!anchor_nid ||
2233ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2243ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
225352f7f91STakashi Iwai 				return path;
2261da177e4SLinus Torvalds 		}
227f5172a7eSTakashi Iwai 	}
2281da177e4SLinus Torvalds 	return NULL;
2291da177e4SLinus Torvalds }
230f5172a7eSTakashi Iwai 
231f5172a7eSTakashi Iwai /* get the path between the given NIDs;
232f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
233f5172a7eSTakashi Iwai  */
234f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
235f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
236f5172a7eSTakashi Iwai {
2373ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
238f5172a7eSTakashi Iwai }
239352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
2401da177e4SLinus Torvalds 
241196c1766STakashi Iwai /* get the index number corresponding to the path instance;
242196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
243196c1766STakashi Iwai  */
244196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
245196c1766STakashi Iwai {
246196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
247196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
248196c1766STakashi Iwai 	ssize_t idx;
249196c1766STakashi Iwai 
250196c1766STakashi Iwai 	if (!spec->paths.used)
251196c1766STakashi Iwai 		return 0;
252196c1766STakashi Iwai 	idx = path - array;
253196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
254196c1766STakashi Iwai 		return 0;
255196c1766STakashi Iwai 	return idx + 1;
256196c1766STakashi Iwai }
257196c1766STakashi Iwai 
258196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
259196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
260196c1766STakashi Iwai {
261196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
262196c1766STakashi Iwai 
263196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
264196c1766STakashi Iwai 		return NULL;
265196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
266196c1766STakashi Iwai }
267196c1766STakashi Iwai 
268352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
269352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
2701da177e4SLinus Torvalds {
271352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
272352f7f91STakashi Iwai 	int i;
273352f7f91STakashi Iwai 
274352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
275352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
276352f7f91STakashi Iwai 		if (path->path[0] == nid)
277352f7f91STakashi Iwai 			return true;
278352f7f91STakashi Iwai 	}
279352f7f91STakashi Iwai 	return false;
2801da177e4SLinus Torvalds }
2811da177e4SLinus Torvalds 
282352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
283352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
284352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
2851da177e4SLinus Torvalds {
286352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
287352f7f91STakashi Iwai 		return false;
288352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
2891da177e4SLinus Torvalds }
2901da177e4SLinus Torvalds 
291352f7f91STakashi Iwai /* nid, dir and idx */
292352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
293352f7f91STakashi Iwai 
294352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
295352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
2961da177e4SLinus Torvalds {
297352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
298352f7f91STakashi Iwai 	int i;
299352f7f91STakashi Iwai 
300352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
301352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
302352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
303352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
304352f7f91STakashi Iwai 			return true;
305352f7f91STakashi Iwai 	}
306352f7f91STakashi Iwai 	return false;
3071da177e4SLinus Torvalds }
3081da177e4SLinus Torvalds 
309352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
310352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
311cb53c626STakashi Iwai 			      int dir, int idx)
312cb53c626STakashi Iwai {
313352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
314352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
315352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
316cb53c626STakashi Iwai }
317352f7f91STakashi Iwai 
3180c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
3190c8c0f56STakashi Iwai {
3200c8c0f56STakashi Iwai 	char buf[40];
3210c8c0f56STakashi Iwai 	int i;
3220c8c0f56STakashi Iwai 
3230c8c0f56STakashi Iwai 
3240c8c0f56STakashi Iwai 	buf[0] = 0;
3250c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
3260c8c0f56STakashi Iwai 		char tmp[4];
3270c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
3280c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
3290c8c0f56STakashi Iwai 	}
3300c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
3310c8c0f56STakashi Iwai }
3320c8c0f56STakashi Iwai 
333352f7f91STakashi Iwai /* called recursively */
334352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
335352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3363ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3373ca529d3STakashi Iwai 			     int depth)
338352f7f91STakashi Iwai {
339ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
340352f7f91STakashi Iwai 	int i, nums;
341352f7f91STakashi Iwai 
3423ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3433ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3443ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3453ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
346352f7f91STakashi Iwai 
347ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
348352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
349352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
350352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
351352f7f91STakashi Iwai 			 * try to find an empty DAC
352352f7f91STakashi Iwai 			 */
353352f7f91STakashi Iwai 			if (from_nid ||
354352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
355352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
356352f7f91STakashi Iwai 				continue;
357352f7f91STakashi Iwai 		}
3583ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
3593ca529d3STakashi Iwai 		if (anchor_nid <= 0)
360352f7f91STakashi Iwai 			goto found;
361352f7f91STakashi Iwai 	}
362352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
363352f7f91STakashi Iwai 		return false;
364352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
365352f7f91STakashi Iwai 		unsigned int type;
366352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
367352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
368352f7f91STakashi Iwai 		    type == AC_WID_PIN)
369352f7f91STakashi Iwai 			continue;
370352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
3713ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
372352f7f91STakashi Iwai 			goto found;
373352f7f91STakashi Iwai 	}
374352f7f91STakashi Iwai 	return false;
375352f7f91STakashi Iwai 
376352f7f91STakashi Iwai  found:
377352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
378352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
379352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
380352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
381352f7f91STakashi Iwai 	path->depth++;
382352f7f91STakashi Iwai 	return true;
383352f7f91STakashi Iwai }
384352f7f91STakashi Iwai 
385352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
386352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
3873ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
3883ca529d3STakashi Iwai  * with the given value are evaluated.
3893ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
3903ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
3913ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
392352f7f91STakashi Iwai  */
393352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
3943ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
395352f7f91STakashi Iwai 			    struct nid_path *path)
396352f7f91STakashi Iwai {
3973ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
398352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
399352f7f91STakashi Iwai 		path->depth++;
400352f7f91STakashi Iwai 		return true;
401352f7f91STakashi Iwai 	}
402352f7f91STakashi Iwai 	return false;
403352f7f91STakashi Iwai }
404352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
405352f7f91STakashi Iwai 
406352f7f91STakashi Iwai /*
407352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
408352f7f91STakashi Iwai  * if no valid path is found, return NULL
409352f7f91STakashi Iwai  */
410352f7f91STakashi Iwai struct nid_path *
411352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4123ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
413352f7f91STakashi Iwai {
414352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
415352f7f91STakashi Iwai 	struct nid_path *path;
416352f7f91STakashi Iwai 
417352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
418352f7f91STakashi Iwai 		return NULL;
419352f7f91STakashi Iwai 
420f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4213ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
422f5172a7eSTakashi Iwai 	if (path)
423f5172a7eSTakashi Iwai 		return path;
424f5172a7eSTakashi Iwai 
425352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
426352f7f91STakashi Iwai 	if (!path)
427352f7f91STakashi Iwai 		return NULL;
428352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4293ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
430352f7f91STakashi Iwai 		return path;
431352f7f91STakashi Iwai 	/* push back */
432352f7f91STakashi Iwai 	spec->paths.used--;
433352f7f91STakashi Iwai 	return NULL;
434352f7f91STakashi Iwai }
435352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
436352f7f91STakashi Iwai 
437980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
438980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
439980428ceSTakashi Iwai {
440980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
441980428ceSTakashi Iwai 	if (!path)
442980428ceSTakashi Iwai 		return;
443980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
444980428ceSTakashi Iwai }
445980428ceSTakashi Iwai 
446352f7f91STakashi Iwai /* look for an empty DAC slot */
447352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
448352f7f91STakashi Iwai 			      bool is_digital)
449352f7f91STakashi Iwai {
450352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
451352f7f91STakashi Iwai 	bool cap_digital;
452352f7f91STakashi Iwai 	int i;
453352f7f91STakashi Iwai 
454352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
455352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
456352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
457352f7f91STakashi Iwai 			continue;
458352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
459352f7f91STakashi Iwai 		if (is_digital != cap_digital)
460352f7f91STakashi Iwai 			continue;
461352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
462352f7f91STakashi Iwai 			return nid;
463352f7f91STakashi Iwai 	}
464352f7f91STakashi Iwai 	return 0;
465352f7f91STakashi Iwai }
466352f7f91STakashi Iwai 
467352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
468352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
469352f7f91STakashi Iwai {
470352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
471352f7f91STakashi Iwai 	val |= chs << 16;
472352f7f91STakashi Iwai 	return val;
473352f7f91STakashi Iwai }
474352f7f91STakashi Iwai 
475352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
476352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
477352f7f91STakashi Iwai 			   int dir, unsigned int bits)
478352f7f91STakashi Iwai {
479352f7f91STakashi Iwai 	if (!nid)
480352f7f91STakashi Iwai 		return false;
481352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
482352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
483352f7f91STakashi Iwai 			return true;
484352f7f91STakashi Iwai 	return false;
485352f7f91STakashi Iwai }
486352f7f91STakashi Iwai 
487352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
488352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
489352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
490352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
491352f7f91STakashi Iwai 
492352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
493352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
494352f7f91STakashi Iwai 				       struct nid_path *path)
495352f7f91STakashi Iwai {
496352f7f91STakashi Iwai 	int i;
497352f7f91STakashi Iwai 
498352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
499352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
500352f7f91STakashi Iwai 			return path->path[i];
501352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
502352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
503352f7f91STakashi Iwai 			return path->path[i];
504352f7f91STakashi Iwai 	}
505352f7f91STakashi Iwai 	return 0;
506352f7f91STakashi Iwai }
507352f7f91STakashi Iwai 
508352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
509352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_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_volume(codec, path->path[i], HDA_OUTPUT))
516352f7f91STakashi Iwai 			return path->path[i];
517352f7f91STakashi Iwai 	}
518352f7f91STakashi Iwai 	return 0;
519352f7f91STakashi Iwai }
520352f7f91STakashi Iwai 
521352f7f91STakashi Iwai /*
522352f7f91STakashi Iwai  * path activation / deactivation
523352f7f91STakashi Iwai  */
524352f7f91STakashi Iwai 
525352f7f91STakashi Iwai /* can have the amp-in capability? */
526352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
527352f7f91STakashi Iwai {
528352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
529352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
530352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
531352f7f91STakashi Iwai 
532352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
533352f7f91STakashi Iwai 		return false;
534352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
535352f7f91STakashi Iwai 		return false;
536352f7f91STakashi Iwai 	return true;
537352f7f91STakashi Iwai }
538352f7f91STakashi Iwai 
539352f7f91STakashi Iwai /* can have the amp-out capability? */
540352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
541352f7f91STakashi Iwai {
542352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
543352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
544352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
545352f7f91STakashi Iwai 
546352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
547352f7f91STakashi Iwai 		return false;
548352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
549352f7f91STakashi Iwai 		return false;
550352f7f91STakashi Iwai 	return true;
551352f7f91STakashi Iwai }
552352f7f91STakashi Iwai 
553352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
554352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
555352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
556352f7f91STakashi Iwai {
557352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
558352f7f91STakashi Iwai 	int i, n;
559352f7f91STakashi Iwai 
560352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
561352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
562352f7f91STakashi Iwai 		if (!path->active)
563352f7f91STakashi Iwai 			continue;
564352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
565352f7f91STakashi Iwai 			if (path->path[i] == nid) {
566352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
567352f7f91STakashi Iwai 					return true;
568352f7f91STakashi Iwai 				break;
569352f7f91STakashi Iwai 			}
570352f7f91STakashi Iwai 		}
571352f7f91STakashi Iwai 	}
572352f7f91STakashi Iwai 	return false;
573352f7f91STakashi Iwai }
574352f7f91STakashi Iwai 
575352f7f91STakashi Iwai /* get the default amp value for the target state */
576352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
577352f7f91STakashi Iwai 				   int dir, bool enable)
578352f7f91STakashi Iwai {
579352f7f91STakashi Iwai 	unsigned int caps;
580352f7f91STakashi Iwai 	unsigned int val = 0;
581352f7f91STakashi Iwai 
582352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
583352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
584352f7f91STakashi Iwai 		/* set to 0dB */
585352f7f91STakashi Iwai 		if (enable)
586352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
587352f7f91STakashi Iwai 	}
588352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
589352f7f91STakashi Iwai 		if (!enable)
590352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
591352f7f91STakashi Iwai 	}
592352f7f91STakashi Iwai 	return val;
593352f7f91STakashi Iwai }
594352f7f91STakashi Iwai 
595352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
596352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
597352f7f91STakashi Iwai {
598352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
599352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
600352f7f91STakashi Iwai }
601352f7f91STakashi Iwai 
602352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
603352f7f91STakashi Iwai 			 int idx, bool enable)
604352f7f91STakashi Iwai {
605352f7f91STakashi Iwai 	int val;
606352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
607985803caSTakashi Iwai 	    (!enable && is_active_nid(codec, nid, dir, idx)))
608352f7f91STakashi Iwai 		return;
609352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
610352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
611352f7f91STakashi Iwai }
612352f7f91STakashi Iwai 
613352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
614352f7f91STakashi Iwai 			     int i, bool enable)
615352f7f91STakashi Iwai {
616352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
617352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
618352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
619352f7f91STakashi Iwai }
620352f7f91STakashi Iwai 
621352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
622352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
623352f7f91STakashi Iwai {
624352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
625ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
626352f7f91STakashi Iwai 	int n, nums, idx;
627352f7f91STakashi Iwai 	int type;
628352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
629352f7f91STakashi Iwai 
630ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
631352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
632352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
633352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
634352f7f91STakashi Iwai 		nums = 1;
635352f7f91STakashi Iwai 		idx = 0;
636352f7f91STakashi Iwai 	} else
637352f7f91STakashi Iwai 		idx = path->idx[i];
638352f7f91STakashi Iwai 
639352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
640352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
641352f7f91STakashi Iwai 
642352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
643352f7f91STakashi Iwai 		return;
644352f7f91STakashi Iwai 
645352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
646352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
647352f7f91STakashi Iwai 	 */
648352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
649352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
650352f7f91STakashi Iwai 			continue;
651352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
652352f7f91STakashi Iwai 	}
653352f7f91STakashi Iwai }
654352f7f91STakashi Iwai 
655352f7f91STakashi Iwai /* activate or deactivate the given path
656352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
657352f7f91STakashi Iwai  */
658352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
659352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
660352f7f91STakashi Iwai {
661352f7f91STakashi Iwai 	int i;
662352f7f91STakashi Iwai 
663352f7f91STakashi Iwai 	if (!enable)
664352f7f91STakashi Iwai 		path->active = false;
665352f7f91STakashi Iwai 
666352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
667352f7f91STakashi Iwai 		if (enable && path->multi[i])
668352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
669352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
670352f7f91STakashi Iwai 					    path->idx[i]);
671352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
672352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
673352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
674352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
675352f7f91STakashi Iwai 	}
676352f7f91STakashi Iwai 
677352f7f91STakashi Iwai 	if (enable)
678352f7f91STakashi Iwai 		path->active = true;
679352f7f91STakashi Iwai }
680352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
681352f7f91STakashi Iwai 
682d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
683d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
684d5a9f1bbSTakashi Iwai {
685d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
686d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
687d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
688d5a9f1bbSTakashi Iwai 		return;
689ecac3ed1STakashi Iwai 	if (codec->inv_eapd)
690ecac3ed1STakashi Iwai 		enable = !enable;
691d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
692d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
693d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
694d5a9f1bbSTakashi Iwai }
695d5a9f1bbSTakashi Iwai 
696352f7f91STakashi Iwai 
697352f7f91STakashi Iwai /*
698352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
699352f7f91STakashi Iwai  */
700352f7f91STakashi Iwai 
701352f7f91STakashi Iwai enum {
702352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
703352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
704352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
705352f7f91STakashi Iwai };
706352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
707352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
708352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
709352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
710352f7f91STakashi Iwai };
711352f7f91STakashi Iwai 
712352f7f91STakashi Iwai /* add dynamic controls from template */
713352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
714352f7f91STakashi Iwai 		       int cidx, unsigned long val)
715352f7f91STakashi Iwai {
716352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
717352f7f91STakashi Iwai 
71812c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
719352f7f91STakashi Iwai 	if (!knew)
720352f7f91STakashi Iwai 		return -ENOMEM;
721352f7f91STakashi Iwai 	knew->index = cidx;
722352f7f91STakashi Iwai 	if (get_amp_nid_(val))
723352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
724352f7f91STakashi Iwai 	knew->private_value = val;
725352f7f91STakashi Iwai 	return 0;
726352f7f91STakashi Iwai }
727352f7f91STakashi Iwai 
728352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
729352f7f91STakashi Iwai 				const char *pfx, const char *dir,
730352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
731352f7f91STakashi Iwai {
732352f7f91STakashi Iwai 	char name[32];
733352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
734352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
735352f7f91STakashi Iwai }
736352f7f91STakashi Iwai 
737352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
738352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
739352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
740352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
741352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
742352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
743352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
744352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
745352f7f91STakashi Iwai 
746352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
747352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
748352f7f91STakashi Iwai {
749352f7f91STakashi Iwai 	unsigned int val;
750352f7f91STakashi Iwai 	if (!path)
751352f7f91STakashi Iwai 		return 0;
752352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
753352f7f91STakashi Iwai 	if (!val)
754352f7f91STakashi Iwai 		return 0;
755352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
756352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
757352f7f91STakashi Iwai }
758352f7f91STakashi Iwai 
759352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
760352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
761352f7f91STakashi Iwai 			       int type)
762352f7f91STakashi Iwai {
763352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
764352f7f91STakashi Iwai 	if (path) {
765352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
766352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
767352f7f91STakashi Iwai 			chs = 3; /* stereo */
768352f7f91STakashi Iwai 	}
769352f7f91STakashi Iwai 	return chs;
770352f7f91STakashi Iwai }
771352f7f91STakashi Iwai 
772352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
773352f7f91STakashi Iwai 			  struct nid_path *path)
774352f7f91STakashi Iwai {
775352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
776352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
777352f7f91STakashi Iwai }
778352f7f91STakashi Iwai 
779352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
780352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
781352f7f91STakashi Iwai  */
782352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
783352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
784352f7f91STakashi Iwai {
785352f7f91STakashi Iwai 	unsigned int val;
786352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
787352f7f91STakashi Iwai 
788352f7f91STakashi Iwai 	if (!path)
789352f7f91STakashi Iwai 		return 0;
790352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
791352f7f91STakashi Iwai 	if (!val)
792352f7f91STakashi Iwai 		return 0;
793352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
794352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
795352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
796352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
797352f7f91STakashi Iwai 		if (nums > 1) {
798352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
799352f7f91STakashi Iwai 			val |= nums << 19;
800352f7f91STakashi Iwai 		}
801352f7f91STakashi Iwai 	}
802352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
803352f7f91STakashi Iwai }
804352f7f91STakashi Iwai 
805352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
806352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
807352f7f91STakashi Iwai {
808352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
809352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
810352f7f91STakashi Iwai }
811352f7f91STakashi Iwai 
812352f7f91STakashi Iwai static const char * const channel_name[4] = {
813352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
814352f7f91STakashi Iwai };
815352f7f91STakashi Iwai 
816352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
817352f7f91STakashi Iwai static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch,
818352f7f91STakashi Iwai 				    bool can_be_master, int *index)
819352f7f91STakashi Iwai {
820352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
821352f7f91STakashi Iwai 
822352f7f91STakashi Iwai 	*index = 0;
823352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
824352f7f91STakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
825352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
826352f7f91STakashi Iwai 
827352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
828352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
829352f7f91STakashi Iwai 	 */
830352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
831352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
832352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
833352f7f91STakashi Iwai 
834352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
835352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
836352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
837352f7f91STakashi Iwai 			return "Speaker";
838352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
839352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
840352f7f91STakashi Iwai 		break;
841352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
842352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
843352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
844352f7f91STakashi Iwai 			break;
845352f7f91STakashi Iwai 		*index = ch;
846352f7f91STakashi Iwai 		return "Headphone";
847352f7f91STakashi Iwai 	default:
848352f7f91STakashi Iwai 		if (cfg->line_outs == 1 && !spec->multi_ios)
849352f7f91STakashi Iwai 			return "PCM";
850352f7f91STakashi Iwai 		break;
851352f7f91STakashi Iwai 	}
852352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
853352f7f91STakashi Iwai 		snd_BUG();
854352f7f91STakashi Iwai 		return "PCM";
855352f7f91STakashi Iwai 	}
856352f7f91STakashi Iwai 
857352f7f91STakashi Iwai 	return channel_name[ch];
858352f7f91STakashi Iwai }
859352f7f91STakashi Iwai 
860352f7f91STakashi Iwai /*
861352f7f91STakashi Iwai  * Parse output paths
862352f7f91STakashi Iwai  */
863352f7f91STakashi Iwai 
864352f7f91STakashi Iwai /* badness definition */
865352f7f91STakashi Iwai enum {
866352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
867352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
868352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
869352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
870352f7f91STakashi Iwai 	/* No possible multi-ios */
871352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
872352f7f91STakashi Iwai 	/* No individual DAC for extra output */
873352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
874352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
875352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
876352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
877352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
878352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
879352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
880352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
881352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
882352f7f91STakashi Iwai 	/* Volume widget is shared */
883352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
884352f7f91STakashi Iwai };
885352f7f91STakashi Iwai 
8860e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
887352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
888352f7f91STakashi Iwai  *
889352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
890352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
891352f7f91STakashi Iwai  * total badness for both volume and mute controls.
892352f7f91STakashi Iwai  */
8930e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
894352f7f91STakashi Iwai {
895352f7f91STakashi Iwai 	hda_nid_t nid;
896352f7f91STakashi Iwai 	unsigned int val;
897352f7f91STakashi Iwai 	int badness = 0;
898352f7f91STakashi Iwai 
899352f7f91STakashi Iwai 	if (!path)
900352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
9010e614dd0STakashi Iwai 
9020e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
9030e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
9040e614dd0STakashi Iwai 		return 0; /* already evaluated */
9050e614dd0STakashi Iwai 
906352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
907352f7f91STakashi Iwai 	if (nid) {
908352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
909352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
910352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
911352f7f91STakashi Iwai 		else
912352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
913352f7f91STakashi Iwai 	} else
914352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
915352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
916352f7f91STakashi Iwai 	if (nid) {
917352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
918352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
919352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
920352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
921352f7f91STakashi Iwai 		else
922352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
923352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
924352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
925352f7f91STakashi Iwai 		else
926352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
927352f7f91STakashi Iwai 	} else
928352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
929352f7f91STakashi Iwai 	return badness;
930352f7f91STakashi Iwai }
931352f7f91STakashi Iwai 
932352f7f91STakashi Iwai struct badness_table {
933352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
934352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
935352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
936352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
937352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
938352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
939352f7f91STakashi Iwai };
940352f7f91STakashi Iwai 
941352f7f91STakashi Iwai static struct badness_table main_out_badness = {
942352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
943352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
944352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
945352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
946352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
947352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
948352f7f91STakashi Iwai };
949352f7f91STakashi Iwai 
950352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
951352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
952352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
953352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
954352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
955352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
956352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
957352f7f91STakashi Iwai };
958352f7f91STakashi Iwai 
9597385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
9607385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
9617385df61STakashi Iwai {
9627385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
9637385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
9647385df61STakashi Iwai 
9657385df61STakashi Iwai 	if (cfg->line_outs > idx)
9667385df61STakashi Iwai 		return spec->private_dac_nids[idx];
9677385df61STakashi Iwai 	idx -= cfg->line_outs;
9687385df61STakashi Iwai 	if (spec->multi_ios > idx)
9697385df61STakashi Iwai 		return spec->multi_io[idx].dac;
9707385df61STakashi Iwai 	return 0;
9717385df61STakashi Iwai }
9727385df61STakashi Iwai 
9737385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
9747385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
9757385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
9767385df61STakashi Iwai {
9777385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
9787385df61STakashi Iwai }
9797385df61STakashi Iwai 
980352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
981352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
982352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
983196c1766STakashi Iwai 			   int *path_idx,
984352f7f91STakashi Iwai 			   const struct badness_table *bad)
985352f7f91STakashi Iwai {
986352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
987352f7f91STakashi Iwai 	int i, j;
988352f7f91STakashi Iwai 	int badness = 0;
989352f7f91STakashi Iwai 	hda_nid_t dac;
990352f7f91STakashi Iwai 
991352f7f91STakashi Iwai 	if (!num_outs)
992352f7f91STakashi Iwai 		return 0;
993352f7f91STakashi Iwai 
994352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
9950c8c0f56STakashi Iwai 		struct nid_path *path;
996352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
9971e0b5286STakashi Iwai 
9980e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
9990e614dd0STakashi Iwai 		if (path) {
10000e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
10011e0b5286STakashi Iwai 			continue;
10021e0b5286STakashi Iwai 		}
10031e0b5286STakashi Iwai 
1004352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1005352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1006980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1007352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1008352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1009352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1010352f7f91STakashi Iwai 					dacs[j] = 0;
1011980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1012196c1766STakashi Iwai 					path_idx[j] = 0;
1013352f7f91STakashi Iwai 					break;
1014352f7f91STakashi Iwai 				}
1015352f7f91STakashi Iwai 			}
1016352f7f91STakashi Iwai 		}
1017352f7f91STakashi Iwai 		dac = dacs[i];
1018352f7f91STakashi Iwai 		if (!dac) {
10197385df61STakashi Iwai 			if (num_outs > 2)
10207385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
10217385df61STakashi Iwai 			if (!dac)
10227385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
10237385df61STakashi Iwai 			if (!dac)
10247385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1025352f7f91STakashi Iwai 			if (dac) {
1026352f7f91STakashi Iwai 				if (!i)
1027352f7f91STakashi Iwai 					badness += bad->shared_primary;
1028352f7f91STakashi Iwai 				else if (i == 1)
1029352f7f91STakashi Iwai 					badness += bad->shared_surr;
1030352f7f91STakashi Iwai 				else
1031352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1032352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1033352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1034352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1035352f7f91STakashi Iwai 			} else if (!i)
1036352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1037352f7f91STakashi Iwai 			else
1038352f7f91STakashi Iwai 				badness += bad->no_dac;
1039352f7f91STakashi Iwai 		}
10403ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1041117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1042b3a8c745STakashi Iwai 			/* try with aamix */
10433ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1044b3a8c745STakashi Iwai 		}
10450c8c0f56STakashi Iwai 		if (!path)
1046352f7f91STakashi Iwai 			dac = dacs[i] = 0;
1047e1284af7STakashi Iwai 		else {
10480c8c0f56STakashi Iwai 			print_nid_path("output", path);
1049e1284af7STakashi Iwai 			path->active = true;
1050196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
10510e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1052e1284af7STakashi Iwai 		}
1053352f7f91STakashi Iwai 	}
1054352f7f91STakashi Iwai 
1055352f7f91STakashi Iwai 	return badness;
1056352f7f91STakashi Iwai }
1057352f7f91STakashi Iwai 
1058352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1059352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1060352f7f91STakashi Iwai {
1061352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1062352f7f91STakashi Iwai 	int i;
1063352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1064352f7f91STakashi Iwai 
1065352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1066352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1067352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1068352f7f91STakashi Iwai 			continue;
1069352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1070352f7f91STakashi Iwai 			if (nid_found)
1071352f7f91STakashi Iwai 				return 0;
1072352f7f91STakashi Iwai 			nid_found = nid;
1073352f7f91STakashi Iwai 		}
1074352f7f91STakashi Iwai 	}
1075352f7f91STakashi Iwai 	return nid_found;
1076352f7f91STakashi Iwai }
1077352f7f91STakashi Iwai 
1078352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1079352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1080352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1081352f7f91STakashi Iwai {
1082352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1083352f7f91STakashi Iwai 
1084352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1085352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1086352f7f91STakashi Iwai 		return false;
1087352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1088352f7f91STakashi Iwai 		return false;
1089352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1090352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1091352f7f91STakashi Iwai 		return false;
1092352f7f91STakashi Iwai 	return true;
1093352f7f91STakashi Iwai }
1094352f7f91STakashi Iwai 
1095e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1096e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1097e22aab7dSTakashi Iwai {
1098e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1099e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1100e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1101e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1102e22aab7dSTakashi Iwai 	int type, i;
1103e22aab7dSTakashi Iwai 	int num_pins = 0;
1104e22aab7dSTakashi Iwai 
1105e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1106e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1107e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1108e22aab7dSTakashi Iwai 				continue;
1109e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1110e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1111e22aab7dSTakashi Iwai 				num_pins++;
1112e22aab7dSTakashi Iwai 		}
1113e22aab7dSTakashi Iwai 	}
1114e22aab7dSTakashi Iwai 	return num_pins;
1115e22aab7dSTakashi Iwai }
1116e22aab7dSTakashi Iwai 
1117352f7f91STakashi Iwai /*
1118352f7f91STakashi Iwai  * multi-io helper
1119352f7f91STakashi Iwai  *
1120352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1121352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1122352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1123352f7f91STakashi Iwai  * the badness value.
1124352f7f91STakashi Iwai  */
1125352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1126352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1127e22aab7dSTakashi Iwai 			  bool hardwired)
1128352f7f91STakashi Iwai {
1129352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1130352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1131e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1132352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1133352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1134352f7f91STakashi Iwai 	int badness = 0;
11350e614dd0STakashi Iwai 	struct nid_path *path;
1136352f7f91STakashi Iwai 
1137352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1138352f7f91STakashi Iwai 	if (old_pins >= 2)
1139352f7f91STakashi Iwai 		goto end_fill;
1140352f7f91STakashi Iwai 
1141e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1142352f7f91STakashi Iwai 	if (num_pins < 2)
1143352f7f91STakashi Iwai 		goto end_fill;
1144352f7f91STakashi Iwai 
1145352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1146352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1147352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1148352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1149352f7f91STakashi Iwai 
1150352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1151352f7f91STakashi Iwai 				continue;
1152352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1153352f7f91STakashi Iwai 				continue;
1154352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1155352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1156352f7f91STakashi Iwai 					break;
1157352f7f91STakashi Iwai 			}
1158352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1159352f7f91STakashi Iwai 				continue;
1160352f7f91STakashi Iwai 
1161352f7f91STakashi Iwai 			if (hardwired)
1162352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1163352f7f91STakashi Iwai 			else if (!dac)
1164352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1165352f7f91STakashi Iwai 			if (!dac) {
1166352f7f91STakashi Iwai 				badness++;
1167352f7f91STakashi Iwai 				continue;
1168352f7f91STakashi Iwai 			}
11693ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
11703ca529d3STakashi Iwai 						    -spec->mixer_nid);
11710c8c0f56STakashi Iwai 			if (!path) {
1172352f7f91STakashi Iwai 				badness++;
1173352f7f91STakashi Iwai 				continue;
1174352f7f91STakashi Iwai 			}
11750c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1176352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1177352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1178196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1179196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1180352f7f91STakashi Iwai 			spec->multi_ios++;
1181352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1182352f7f91STakashi Iwai 				break;
1183352f7f91STakashi Iwai 		}
1184352f7f91STakashi Iwai 	}
1185352f7f91STakashi Iwai  end_fill:
1186352f7f91STakashi Iwai 	if (badness)
1187352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1188352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1189352f7f91STakashi Iwai 		if (hardwired)
1190352f7f91STakashi Iwai 			return 1; /* nothing found */
1191352f7f91STakashi Iwai 		else
1192352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1193352f7f91STakashi Iwai 	}
1194352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1195352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1196352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1197352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1198352f7f91STakashi Iwai 		return badness;
1199352f7f91STakashi Iwai 	}
1200352f7f91STakashi Iwai 
1201352f7f91STakashi Iwai 	/* assign volume and mute controls */
12020e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
12030e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
12040e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
12050e614dd0STakashi Iwai 	}
1206352f7f91STakashi Iwai 
1207352f7f91STakashi Iwai 	return badness;
1208352f7f91STakashi Iwai }
1209352f7f91STakashi Iwai 
1210352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1211352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1212196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1213352f7f91STakashi Iwai {
1214b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1215352f7f91STakashi Iwai 	int i;
1216352f7f91STakashi Iwai 	bool found = false;
1217352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
12180c8c0f56STakashi Iwai 		struct nid_path *path;
1219352f7f91STakashi Iwai 		hda_nid_t dac;
1220352f7f91STakashi Iwai 		if (dacs[i])
1221352f7f91STakashi Iwai 			continue;
1222352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1223352f7f91STakashi Iwai 		if (!dac)
1224352f7f91STakashi Iwai 			continue;
12253ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
12263ca529d3STakashi Iwai 					    -spec->mixer_nid);
1227117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
12283ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
12290c8c0f56STakashi Iwai 		if (path) {
1230352f7f91STakashi Iwai 			dacs[i] = dac;
1231352f7f91STakashi Iwai 			found = true;
12320c8c0f56STakashi Iwai 			print_nid_path("output", path);
1233e1284af7STakashi Iwai 			path->active = true;
1234196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1235352f7f91STakashi Iwai 		}
1236352f7f91STakashi Iwai 	}
1237352f7f91STakashi Iwai 	return found;
1238352f7f91STakashi Iwai }
1239352f7f91STakashi Iwai 
1240c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1241c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1242c30aa7b2STakashi Iwai {
12433ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1244c30aa7b2STakashi Iwai 	struct nid_path *path;
1245c30aa7b2STakashi Iwai 
1246c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
12473ca529d3STakashi Iwai 	if (!path || !path->depth ||
12483ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1249c30aa7b2STakashi Iwai 		return 0;
1250c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1251c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
12523ca529d3STakashi Iwai 				    spec->mixer_nid);
1253c30aa7b2STakashi Iwai 	if (!path)
1254c30aa7b2STakashi Iwai 		return 0;
1255c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1256c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1257c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1258c30aa7b2STakashi Iwai }
1259c30aa7b2STakashi Iwai 
1260a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1261a07a949bSTakashi Iwai  * shared dac pointed by the paths
1262a07a949bSTakashi Iwai  */
1263a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1264a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1265a07a949bSTakashi Iwai {
1266a07a949bSTakashi Iwai 	struct nid_path *path;
1267a07a949bSTakashi Iwai 	int i;
1268a07a949bSTakashi Iwai 
1269a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1270a07a949bSTakashi Iwai 		if (dacs[i])
1271a07a949bSTakashi Iwai 			continue;
1272a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1273a07a949bSTakashi Iwai 		if (!path)
1274a07a949bSTakashi Iwai 			continue;
1275a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1276a07a949bSTakashi Iwai 	}
1277a07a949bSTakashi Iwai }
1278a07a949bSTakashi Iwai 
1279352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1280352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1281352f7f91STakashi Iwai 			      bool fill_hardwired,
1282352f7f91STakashi Iwai 			      bool fill_mio_first)
1283352f7f91STakashi Iwai {
1284352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1285352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1286352f7f91STakashi Iwai 	int i, err, badness;
1287352f7f91STakashi Iwai 
1288352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1289352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1290352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1291352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1292352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1293352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1294352f7f91STakashi Iwai 	spec->multi_ios = 0;
1295352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1296cd5be3f9STakashi Iwai 
1297cd5be3f9STakashi Iwai 	/* clear path indices */
1298cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1299cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1300cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1301cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1302cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1303c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1304cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1305cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1306cd5be3f9STakashi Iwai 
1307352f7f91STakashi Iwai 	badness = 0;
1308352f7f91STakashi Iwai 
1309352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1310352f7f91STakashi Iwai 	if (fill_hardwired) {
1311352f7f91STakashi Iwai 		bool mapped;
1312352f7f91STakashi Iwai 		do {
1313352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1314352f7f91STakashi Iwai 					     cfg->line_out_pins,
1315196c1766STakashi Iwai 					     spec->private_dac_nids,
1316196c1766STakashi Iwai 					     spec->out_paths);
1317352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1318352f7f91STakashi Iwai 					      cfg->hp_pins,
1319196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1320196c1766STakashi Iwai 					      spec->hp_paths);
1321352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1322352f7f91STakashi Iwai 					      cfg->speaker_pins,
1323196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1324196c1766STakashi Iwai 					      spec->speaker_paths);
1325352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1326352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1327e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1328352f7f91STakashi Iwai 				if (!err)
1329352f7f91STakashi Iwai 					mapped = true;
1330352f7f91STakashi Iwai 			}
1331352f7f91STakashi Iwai 		} while (mapped);
1332352f7f91STakashi Iwai 	}
1333352f7f91STakashi Iwai 
1334352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1335196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1336352f7f91STakashi Iwai 				   &main_out_badness);
1337352f7f91STakashi Iwai 
1338352f7f91STakashi Iwai 	if (fill_mio_first &&
1339352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1340352f7f91STakashi Iwai 		/* try to fill multi-io first */
1341e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1342352f7f91STakashi Iwai 		if (err < 0)
1343352f7f91STakashi Iwai 			return err;
1344352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1345352f7f91STakashi Iwai 	}
1346352f7f91STakashi Iwai 
1347352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1348352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1349352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1350196c1766STakashi Iwai 				      spec->hp_paths,
1351352f7f91STakashi Iwai 				      &extra_out_badness);
1352352f7f91STakashi Iwai 		if (err < 0)
1353352f7f91STakashi Iwai 			return err;
1354352f7f91STakashi Iwai 		badness += err;
1355352f7f91STakashi Iwai 	}
1356352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1357352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1358352f7f91STakashi Iwai 				      cfg->speaker_pins,
1359352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1360196c1766STakashi Iwai 				      spec->speaker_paths,
1361352f7f91STakashi Iwai 				      &extra_out_badness);
1362352f7f91STakashi Iwai 		if (err < 0)
1363352f7f91STakashi Iwai 			return err;
1364352f7f91STakashi Iwai 		badness += err;
1365352f7f91STakashi Iwai 	}
1366352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1367e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1368352f7f91STakashi Iwai 		if (err < 0)
1369352f7f91STakashi Iwai 			return err;
1370352f7f91STakashi Iwai 		badness += err;
1371352f7f91STakashi Iwai 	}
1372e22aab7dSTakashi Iwai 
1373c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1374c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1375c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1376c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1377c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1378c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1379c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1380c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1381c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1382c30aa7b2STakashi Iwai 	}
1383c30aa7b2STakashi Iwai 
1384e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1385e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1386e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1387352f7f91STakashi Iwai 
1388a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1389a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1390a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1391a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1392a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1393a07a949bSTakashi Iwai 		else {
1394a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1395a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1396a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1397a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1398a07a949bSTakashi Iwai 		}
1399a07a949bSTakashi Iwai 	}
1400a07a949bSTakashi Iwai 
1401a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1402a07a949bSTakashi Iwai 		spec->multiout.num_dacs;
1403a07a949bSTakashi Iwai 
1404352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1405352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1406352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1407352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1408352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1409352f7f91STakashi Iwai 		spec->multi_ios = 0;
1410352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1411352f7f91STakashi Iwai 	}
1412352f7f91STakashi Iwai 
1413a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1414a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1415a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1416a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1417a07a949bSTakashi Iwai 				   spec->hp_paths);
1418a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1419a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1420a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1421a07a949bSTakashi Iwai 				   spec->speaker_paths);
1422a07a949bSTakashi Iwai 
14232c12c30dSTakashi Iwai 	/* set initial pinctl targets */
14242c12c30dSTakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins,
14252c12c30dSTakashi Iwai 			cfg->line_out_type == AUTO_PIN_HP_OUT ? PIN_HP : PIN_OUT);
14262c12c30dSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
14272c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
14282c12c30dSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
14292c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
14302c12c30dSTakashi Iwai 				cfg->speaker_pins, PIN_OUT);
14312c12c30dSTakashi Iwai 
1432352f7f91STakashi Iwai 	return badness;
1433352f7f91STakashi Iwai }
1434352f7f91STakashi Iwai 
1435352f7f91STakashi Iwai #define DEBUG_BADNESS
1436352f7f91STakashi Iwai 
1437352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1438352f7f91STakashi Iwai #define debug_badness	snd_printdd
1439352f7f91STakashi Iwai #else
1440352f7f91STakashi Iwai #define debug_badness(...)
1441352f7f91STakashi Iwai #endif
1442352f7f91STakashi Iwai 
1443352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1444352f7f91STakashi Iwai {
1445352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1446352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1447708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1448352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1449352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1450352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1451352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1452352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1453352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1454352f7f91STakashi Iwai 			      spec->multi_ios,
1455352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1456352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1457352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1458352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1459708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1460352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1461352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1462352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1463352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1464352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1465352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1466352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1467352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1468352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1469352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1470352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1471352f7f91STakashi Iwai }
1472352f7f91STakashi Iwai 
1473352f7f91STakashi Iwai /* find all available DACs of the codec */
1474352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1475352f7f91STakashi Iwai {
1476352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1477352f7f91STakashi Iwai 	int i;
1478352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1479352f7f91STakashi Iwai 
1480352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1481352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1482352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1483352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1484352f7f91STakashi Iwai 			continue;
1485352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1486352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1487352f7f91STakashi Iwai 			break;
1488352f7f91STakashi Iwai 		}
1489352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1490352f7f91STakashi Iwai 	}
1491352f7f91STakashi Iwai }
1492352f7f91STakashi Iwai 
1493352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1494352f7f91STakashi Iwai {
1495352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1496352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1497352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1498352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1499352f7f91STakashi Iwai 	int badness;
1500352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1501352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1502352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1503352f7f91STakashi Iwai 
1504352f7f91STakashi Iwai 	fill_all_dac_nids(codec);
1505352f7f91STakashi Iwai 
1506352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1507352f7f91STakashi Iwai 	if (!best_cfg)
1508352f7f91STakashi Iwai 		return -ENOMEM;
1509352f7f91STakashi Iwai 	*best_cfg = *cfg;
1510352f7f91STakashi Iwai 
1511352f7f91STakashi Iwai 	for (;;) {
1512352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1513352f7f91STakashi Iwai 					     fill_mio_first);
1514352f7f91STakashi Iwai 		if (badness < 0) {
1515352f7f91STakashi Iwai 			kfree(best_cfg);
1516352f7f91STakashi Iwai 			return badness;
1517352f7f91STakashi Iwai 		}
1518352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1519352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1520352f7f91STakashi Iwai 			      badness);
1521352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1522352f7f91STakashi Iwai 		if (badness < best_badness) {
1523352f7f91STakashi Iwai 			best_badness = badness;
1524352f7f91STakashi Iwai 			*best_cfg = *cfg;
1525352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1526352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1527352f7f91STakashi Iwai 		}
1528352f7f91STakashi Iwai 		if (!badness)
1529352f7f91STakashi Iwai 			break;
1530352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1531352f7f91STakashi Iwai 		if (!fill_mio_first)
1532352f7f91STakashi Iwai 			continue;
1533352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1534352f7f91STakashi Iwai 		if (!fill_hardwired)
1535352f7f91STakashi Iwai 			continue;
1536352f7f91STakashi Iwai 		if (hp_spk_swapped)
1537352f7f91STakashi Iwai 			break;
1538352f7f91STakashi Iwai 		hp_spk_swapped = true;
1539352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1540352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1541352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1542352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1543352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1544352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1545352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1546352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1547352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1548352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1549352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1550352f7f91STakashi Iwai 			fill_hardwired = true;
1551352f7f91STakashi Iwai 			continue;
1552352f7f91STakashi Iwai 		}
1553352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1554352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1555352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1556352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1557352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1558352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1559352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1560352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1561352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1562352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1563352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1564352f7f91STakashi Iwai 			fill_hardwired = true;
1565352f7f91STakashi Iwai 			continue;
1566352f7f91STakashi Iwai 		}
1567352f7f91STakashi Iwai 		break;
1568352f7f91STakashi Iwai 	}
1569352f7f91STakashi Iwai 
1570352f7f91STakashi Iwai 	if (badness) {
15710c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1572352f7f91STakashi Iwai 		*cfg = *best_cfg;
1573352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1574352f7f91STakashi Iwai 	}
1575352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1576352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1577352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1578352f7f91STakashi Iwai 
1579352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1580352f7f91STakashi Iwai 		struct nid_path *path;
1581196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1582352f7f91STakashi Iwai 		if (path)
1583352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1584352f7f91STakashi Iwai 	}
1585352f7f91STakashi Iwai 
1586352f7f91STakashi Iwai 	kfree(best_cfg);
1587352f7f91STakashi Iwai 	return 0;
1588352f7f91STakashi Iwai }
1589352f7f91STakashi Iwai 
1590352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1591352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1592352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1593352f7f91STakashi Iwai {
1594352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1595352f7f91STakashi Iwai 	int i, err, noutputs;
1596352f7f91STakashi Iwai 
1597352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1598352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1599352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1600352f7f91STakashi Iwai 
1601352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1602352f7f91STakashi Iwai 		const char *name;
1603352f7f91STakashi Iwai 		int index;
1604352f7f91STakashi Iwai 		struct nid_path *path;
1605352f7f91STakashi Iwai 
1606352f7f91STakashi Iwai 		if (i >= cfg->line_outs) {
1607352f7f91STakashi Iwai 			index = 0;
1608352f7f91STakashi Iwai 			name = channel_name[i];
1609352f7f91STakashi Iwai 		} else {
1610352f7f91STakashi Iwai 			name = get_line_out_pfx(spec, i, true, &index);
1611352f7f91STakashi Iwai 		}
1612352f7f91STakashi Iwai 
1613196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1614352f7f91STakashi Iwai 		if (!path)
1615352f7f91STakashi Iwai 			continue;
1616352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1617352f7f91STakashi Iwai 			/* Center/LFE */
1618352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1619352f7f91STakashi Iwai 			if (err < 0)
1620352f7f91STakashi Iwai 				return err;
1621352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1622352f7f91STakashi Iwai 			if (err < 0)
1623352f7f91STakashi Iwai 				return err;
1624352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1625352f7f91STakashi Iwai 			if (err < 0)
1626352f7f91STakashi Iwai 				return err;
1627352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1628352f7f91STakashi Iwai 			if (err < 0)
1629352f7f91STakashi Iwai 				return err;
1630352f7f91STakashi Iwai 		} else {
1631352f7f91STakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1632352f7f91STakashi Iwai 			if (err < 0)
1633352f7f91STakashi Iwai 				return err;
1634352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1635352f7f91STakashi Iwai 			if (err < 0)
1636352f7f91STakashi Iwai 				return err;
1637352f7f91STakashi Iwai 		}
1638352f7f91STakashi Iwai 	}
1639352f7f91STakashi Iwai 	return 0;
1640352f7f91STakashi Iwai }
1641352f7f91STakashi Iwai 
1642c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1643196c1766STakashi Iwai 			    const char *pfx, int cidx)
1644352f7f91STakashi Iwai {
1645352f7f91STakashi Iwai 	struct nid_path *path;
1646352f7f91STakashi Iwai 	int err;
1647352f7f91STakashi Iwai 
1648196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1649352f7f91STakashi Iwai 	if (!path)
1650352f7f91STakashi Iwai 		return 0;
1651352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1652352f7f91STakashi Iwai 	if (err < 0)
1653352f7f91STakashi Iwai 		return err;
1654352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1655352f7f91STakashi Iwai 	if (err < 0)
1656352f7f91STakashi Iwai 		return err;
1657352f7f91STakashi Iwai 	return 0;
1658352f7f91STakashi Iwai }
1659352f7f91STakashi Iwai 
1660352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1661352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1662196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1663352f7f91STakashi Iwai {
1664c2c80383STakashi Iwai 	int i;
1665352f7f91STakashi Iwai 
1666352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1667c2c80383STakashi Iwai 		const char *name;
1668c2c80383STakashi Iwai 		char tmp[44];
1669c2c80383STakashi Iwai 		int err, idx = 0;
1670c2c80383STakashi Iwai 
1671c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1672c2c80383STakashi Iwai 			name = "Bass Speaker";
1673c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1674c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1675352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1676c2c80383STakashi Iwai 			name = tmp;
1677352f7f91STakashi Iwai 		} else {
1678c2c80383STakashi Iwai 			name = pfx;
1679c2c80383STakashi Iwai 			idx = i;
1680352f7f91STakashi Iwai 		}
1681c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1682352f7f91STakashi Iwai 		if (err < 0)
1683352f7f91STakashi Iwai 			return err;
1684352f7f91STakashi Iwai 	}
1685352f7f91STakashi Iwai 	return 0;
1686352f7f91STakashi Iwai }
1687352f7f91STakashi Iwai 
1688352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1689352f7f91STakashi Iwai {
1690352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1691352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1692196c1766STakashi Iwai 				 spec->hp_paths,
1693352f7f91STakashi Iwai 				 "Headphone");
1694352f7f91STakashi Iwai }
1695352f7f91STakashi Iwai 
1696352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1697352f7f91STakashi Iwai {
1698352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1699352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1700196c1766STakashi Iwai 				 spec->speaker_paths,
1701352f7f91STakashi Iwai 				 "Speaker");
1702352f7f91STakashi Iwai }
1703352f7f91STakashi Iwai 
1704352f7f91STakashi Iwai /*
170538cf6f1aSTakashi Iwai  * independent HP controls
170638cf6f1aSTakashi Iwai  */
170738cf6f1aSTakashi Iwai 
170838cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
170938cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
171038cf6f1aSTakashi Iwai {
171138cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
171238cf6f1aSTakashi Iwai }
171338cf6f1aSTakashi Iwai 
171438cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
171538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
171638cf6f1aSTakashi Iwai {
171738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
171838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
171938cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
172038cf6f1aSTakashi Iwai 	return 0;
172138cf6f1aSTakashi Iwai }
172238cf6f1aSTakashi Iwai 
172338cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
172438cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
172538cf6f1aSTakashi Iwai {
172638cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
172738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
172838cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
172938cf6f1aSTakashi Iwai 	int ret = 0;
173038cf6f1aSTakashi Iwai 
173138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
173238cf6f1aSTakashi Iwai 	if (spec->active_streams) {
173338cf6f1aSTakashi Iwai 		ret = -EBUSY;
173438cf6f1aSTakashi Iwai 		goto unlock;
173538cf6f1aSTakashi Iwai 	}
173638cf6f1aSTakashi Iwai 
173738cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
173838cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
173938cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
174038cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
174138cf6f1aSTakashi Iwai 		else
174238cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
174338cf6f1aSTakashi Iwai 		ret = 1;
174438cf6f1aSTakashi Iwai 	}
174538cf6f1aSTakashi Iwai  unlock:
174638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
174738cf6f1aSTakashi Iwai 	return ret;
174838cf6f1aSTakashi Iwai }
174938cf6f1aSTakashi Iwai 
175038cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
175138cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
175238cf6f1aSTakashi Iwai 	.name = "Independent HP",
175338cf6f1aSTakashi Iwai 	.info = indep_hp_info,
175438cf6f1aSTakashi Iwai 	.get = indep_hp_get,
175538cf6f1aSTakashi Iwai 	.put = indep_hp_put,
175638cf6f1aSTakashi Iwai };
175738cf6f1aSTakashi Iwai 
175838cf6f1aSTakashi Iwai 
175938cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
176038cf6f1aSTakashi Iwai {
176138cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
176238cf6f1aSTakashi Iwai 
176338cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
176438cf6f1aSTakashi Iwai 		return 0;
176538cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
176638cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
176738cf6f1aSTakashi Iwai 		return 0;
176838cf6f1aSTakashi Iwai 	}
176938cf6f1aSTakashi Iwai 
177038cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
177138cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
177238cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
177338cf6f1aSTakashi Iwai 		return -ENOMEM;
177438cf6f1aSTakashi Iwai 	return 0;
177538cf6f1aSTakashi Iwai }
177638cf6f1aSTakashi Iwai 
177738cf6f1aSTakashi Iwai /*
1778352f7f91STakashi Iwai  * channel mode enum control
1779352f7f91STakashi Iwai  */
1780352f7f91STakashi Iwai 
1781352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1782352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1783352f7f91STakashi Iwai {
1784352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1785352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1786a07a949bSTakashi Iwai 	int chs;
1787352f7f91STakashi Iwai 
1788352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1789352f7f91STakashi Iwai 	uinfo->count = 1;
1790352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1791352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1792352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1793a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
1794a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
1795352f7f91STakashi Iwai 	return 0;
1796352f7f91STakashi Iwai }
1797352f7f91STakashi Iwai 
1798352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1799352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1800352f7f91STakashi Iwai {
1801352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1802352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1803a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
1804a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
1805352f7f91STakashi Iwai 	return 0;
1806352f7f91STakashi Iwai }
1807352f7f91STakashi Iwai 
1808196c1766STakashi Iwai static inline struct nid_path *
1809196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1810196c1766STakashi Iwai {
1811196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1812196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1813196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1814196c1766STakashi Iwai }
1815196c1766STakashi Iwai 
1816352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1817352f7f91STakashi Iwai {
1818352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1819352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1820352f7f91STakashi Iwai 	struct nid_path *path;
1821352f7f91STakashi Iwai 
1822196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1823352f7f91STakashi Iwai 	if (!path)
1824352f7f91STakashi Iwai 		return -EINVAL;
1825352f7f91STakashi Iwai 
1826352f7f91STakashi Iwai 	if (path->active == output)
1827352f7f91STakashi Iwai 		return 0;
1828352f7f91STakashi Iwai 
1829352f7f91STakashi Iwai 	if (output) {
18302c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
1831352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1832d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1833352f7f91STakashi Iwai 	} else {
1834d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1835352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
18362c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
1837352f7f91STakashi Iwai 	}
1838a365fed9STakashi Iwai 
1839a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
1840a365fed9STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
1841a365fed9STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
1842a365fed9STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
1843a365fed9STakashi Iwai 
1844352f7f91STakashi Iwai 	return 0;
1845352f7f91STakashi Iwai }
1846352f7f91STakashi Iwai 
1847352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1848352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1849352f7f91STakashi Iwai {
1850352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1851352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1852352f7f91STakashi Iwai 	int i, ch;
1853352f7f91STakashi Iwai 
1854352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1855352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1856352f7f91STakashi Iwai 		return -EINVAL;
1857a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
1858352f7f91STakashi Iwai 		return 0;
1859a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
1860352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1861352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1862352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1863352f7f91STakashi Iwai 					  spec->const_channel_count);
1864352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1865352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1866352f7f91STakashi Iwai 	return 1;
1867352f7f91STakashi Iwai }
1868352f7f91STakashi Iwai 
1869352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1870352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1871352f7f91STakashi Iwai 	.name = "Channel Mode",
1872352f7f91STakashi Iwai 	.info = ch_mode_info,
1873352f7f91STakashi Iwai 	.get = ch_mode_get,
1874352f7f91STakashi Iwai 	.put = ch_mode_put,
1875352f7f91STakashi Iwai };
1876352f7f91STakashi Iwai 
1877352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1878352f7f91STakashi Iwai {
1879352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1880352f7f91STakashi Iwai 
1881352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
188212c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1883352f7f91STakashi Iwai 			return -ENOMEM;
1884352f7f91STakashi Iwai 	}
1885352f7f91STakashi Iwai 	return 0;
1886352f7f91STakashi Iwai }
1887352f7f91STakashi Iwai 
1888352f7f91STakashi Iwai /*
1889c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1890c30aa7b2STakashi Iwai  */
1891c30aa7b2STakashi Iwai 
1892c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1893c30aa7b2STakashi Iwai 
1894c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1895c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1896c30aa7b2STakashi Iwai {
1897c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1898c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1899c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1900c30aa7b2STakashi Iwai 	return 0;
1901c30aa7b2STakashi Iwai }
1902c30aa7b2STakashi Iwai 
1903c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1904c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1905c30aa7b2STakashi Iwai {
1906c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1907c30aa7b2STakashi Iwai 
1908c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1909c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1910c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1911c30aa7b2STakashi Iwai 		return;
1912c30aa7b2STakashi Iwai 	if (do_mix) {
1913c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1914c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1915c30aa7b2STakashi Iwai 	} else {
1916c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1917c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1918c30aa7b2STakashi Iwai 	}
1919c30aa7b2STakashi Iwai }
1920c30aa7b2STakashi Iwai 
1921c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1922c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1923c30aa7b2STakashi Iwai {
1924c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1925c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1926c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
1927c30aa7b2STakashi Iwai 
1928c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
1929c30aa7b2STakashi Iwai 		return 0;
1930c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
1931c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
1932c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
1933c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
1934c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
1935c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
1936c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
1937c30aa7b2STakashi Iwai 	return 1;
1938c30aa7b2STakashi Iwai }
1939c30aa7b2STakashi Iwai 
1940c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
1941c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1942c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
1943c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
1944c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
1945c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
1946c30aa7b2STakashi Iwai };
1947c30aa7b2STakashi Iwai 
1948c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
1949c30aa7b2STakashi Iwai {
1950c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1951c30aa7b2STakashi Iwai 
1952c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
1953c30aa7b2STakashi Iwai 		return 0;
1954c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1955c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
1956c30aa7b2STakashi Iwai 		return 0;
1957c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
1958c30aa7b2STakashi Iwai 		return -ENOMEM;
1959c30aa7b2STakashi Iwai 	return 0;
1960c30aa7b2STakashi Iwai }
1961c30aa7b2STakashi Iwai 
1962c30aa7b2STakashi Iwai /*
1963352f7f91STakashi Iwai  * shared headphone/mic handling
1964352f7f91STakashi Iwai  */
1965352f7f91STakashi Iwai 
1966352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
1967352f7f91STakashi Iwai 
1968352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
1969352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
1970352f7f91STakashi Iwai {
1971352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1972352f7f91STakashi Iwai 	unsigned int val;
1973352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
1974352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
1975352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
1976352f7f91STakashi Iwai 	 */
1977352f7f91STakashi Iwai 
1978352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
1979352f7f91STakashi Iwai 
1980352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
1981352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
1982352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
1983352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
1984352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
1985352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
19867594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
19877594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
1988352f7f91STakashi Iwai 	}
1989352f7f91STakashi Iwai 
1990352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
19912c12c30dSTakashi Iwai 	set_pin_target(codec, pin, val, true);
1992352f7f91STakashi Iwai 
1993352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
1994352f7f91STakashi Iwai 	call_update_outputs(codec);
1995352f7f91STakashi Iwai }
1996352f7f91STakashi Iwai 
1997352f7f91STakashi Iwai /* create a shared input with the headphone out */
1998352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
1999352f7f91STakashi Iwai {
2000352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2001352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2002352f7f91STakashi Iwai 	unsigned int defcfg;
2003352f7f91STakashi Iwai 	hda_nid_t nid;
2004352f7f91STakashi Iwai 
2005352f7f91STakashi Iwai 	/* only one internal input pin? */
2006352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
2007352f7f91STakashi Iwai 		return 0;
2008352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2009352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2010352f7f91STakashi Iwai 		return 0;
2011352f7f91STakashi Iwai 
2012352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2013352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2014352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2015352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2016352f7f91STakashi Iwai 	else
2017352f7f91STakashi Iwai 		return 0; /* both not available */
2018352f7f91STakashi Iwai 
2019352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2020352f7f91STakashi Iwai 		return 0; /* no input */
2021352f7f91STakashi Iwai 
2022352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
2023352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
2024352f7f91STakashi Iwai 	cfg->num_inputs = 2;
2025352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
2026352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2027352f7f91STakashi Iwai 	return 0;
2028352f7f91STakashi Iwai }
2029352f7f91STakashi Iwai 
2030978e77e7STakashi Iwai /*
2031978e77e7STakashi Iwai  * output jack mode
2032978e77e7STakashi Iwai  */
2033978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2034978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2035978e77e7STakashi Iwai {
2036978e77e7STakashi Iwai 	static const char * const texts[] = {
2037978e77e7STakashi Iwai 		"Line Out", "Headphone Out",
2038978e77e7STakashi Iwai 	};
2039978e77e7STakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
2040978e77e7STakashi Iwai }
2041978e77e7STakashi Iwai 
2042978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2043978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2044978e77e7STakashi Iwai {
2045978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2046978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2047978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2048978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2049978e77e7STakashi Iwai 	else
2050978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2051978e77e7STakashi Iwai 	return 0;
2052978e77e7STakashi Iwai }
2053978e77e7STakashi Iwai 
2054978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2055978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2056978e77e7STakashi Iwai {
2057978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2058978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2059978e77e7STakashi Iwai 	unsigned int val;
2060978e77e7STakashi Iwai 
2061978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2062978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2063978e77e7STakashi Iwai 		return 0;
2064978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2065978e77e7STakashi Iwai 	return 1;
2066978e77e7STakashi Iwai }
2067978e77e7STakashi Iwai 
2068978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2069978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2070978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2071978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2072978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2073978e77e7STakashi Iwai };
2074978e77e7STakashi Iwai 
2075978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2076978e77e7STakashi Iwai {
2077978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2078978e77e7STakashi Iwai 	int i;
2079978e77e7STakashi Iwai 
2080978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2081978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2082978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2083978e77e7STakashi Iwai 			return true;
2084978e77e7STakashi Iwai 	}
2085978e77e7STakashi Iwai 	return false;
2086978e77e7STakashi Iwai }
2087978e77e7STakashi Iwai 
2088978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2089978e77e7STakashi Iwai 			       char *name, size_t name_len)
2090978e77e7STakashi Iwai {
2091978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2092978e77e7STakashi Iwai 	int idx = 0;
2093978e77e7STakashi Iwai 
2094978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2095978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2096978e77e7STakashi Iwai 
2097978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2098978e77e7STakashi Iwai 		;
2099978e77e7STakashi Iwai }
2100978e77e7STakashi Iwai 
2101978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2102978e77e7STakashi Iwai 				 hda_nid_t *pins)
2103978e77e7STakashi Iwai {
2104978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2105978e77e7STakashi Iwai 	int i;
2106978e77e7STakashi Iwai 
2107978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2108978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2109978e77e7STakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2110978e77e7STakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
2111978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2112978e77e7STakashi Iwai 			char name[44];
2113978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2114978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2115978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2116978e77e7STakashi Iwai 			if (!knew)
2117978e77e7STakashi Iwai 				return -ENOMEM;
2118978e77e7STakashi Iwai 			knew->private_value = pin;
2119978e77e7STakashi Iwai 		}
2120978e77e7STakashi Iwai 	}
2121978e77e7STakashi Iwai 
2122978e77e7STakashi Iwai 	return 0;
2123978e77e7STakashi Iwai }
2124978e77e7STakashi Iwai 
2125352f7f91STakashi Iwai 
2126352f7f91STakashi Iwai /*
2127352f7f91STakashi Iwai  * Parse input paths
2128352f7f91STakashi Iwai  */
2129352f7f91STakashi Iwai 
2130352f7f91STakashi Iwai #ifdef CONFIG_PM
2131352f7f91STakashi Iwai /* add the powersave loopback-list entry */
2132352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2133352f7f91STakashi Iwai {
2134352f7f91STakashi Iwai 	struct hda_amp_list *list;
2135352f7f91STakashi Iwai 
2136352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
2137352f7f91STakashi Iwai 		return;
2138352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
2139352f7f91STakashi Iwai 	list->nid = mix;
2140352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2141352f7f91STakashi Iwai 	list->idx = idx;
2142352f7f91STakashi Iwai 	spec->num_loopbacks++;
2143cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
2144cb53c626STakashi Iwai }
2145cb53c626STakashi Iwai #else
2146352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
2147cb53c626STakashi Iwai #endif
2148cb53c626STakashi Iwai 
2149352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2150196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2151196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2152352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
21531da177e4SLinus Torvalds {
2154352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2155352f7f91STakashi Iwai 	struct nid_path *path;
2156352f7f91STakashi Iwai 	unsigned int val;
2157352f7f91STakashi Iwai 	int err, idx;
21581da177e4SLinus Torvalds 
2159352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
2160352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
2161352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
2162352f7f91STakashi Iwai 
21633ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2164352f7f91STakashi Iwai 	if (!path)
2165352f7f91STakashi Iwai 		return -EINVAL;
21660c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2167196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2168352f7f91STakashi Iwai 
2169352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
2170352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
2171352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2172352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
2173d13bd412STakashi Iwai 		if (err < 0)
21741da177e4SLinus Torvalds 			return err;
2175352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
21761da177e4SLinus Torvalds 	}
21771da177e4SLinus Torvalds 
2178352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
2179352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2180352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
2181d13bd412STakashi Iwai 		if (err < 0)
21821da177e4SLinus Torvalds 			return err;
2183352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
21841da177e4SLinus Torvalds 	}
21851da177e4SLinus Torvalds 
2186352f7f91STakashi Iwai 	path->active = true;
2187352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
2188352f7f91STakashi Iwai 	return 0;
21891da177e4SLinus Torvalds }
21901da177e4SLinus Torvalds 
2191352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
21921da177e4SLinus Torvalds {
2193352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2194352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2195352f7f91STakashi Iwai }
2196352f7f91STakashi Iwai 
2197352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2198352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2199352f7f91STakashi Iwai {
2200352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2201352f7f91STakashi Iwai 	hda_nid_t nid;
2202352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2203352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2204352f7f91STakashi Iwai 	int i, nums = 0;
2205352f7f91STakashi Iwai 
2206352f7f91STakashi Iwai 	nid = codec->start_nid;
2207352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2208352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2209352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2210352f7f91STakashi Iwai 
2211352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2212352f7f91STakashi Iwai 			continue;
2213352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2214352f7f91STakashi Iwai 		if (++nums >= max_nums)
2215352f7f91STakashi Iwai 			break;
2216352f7f91STakashi Iwai 	}
2217352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
2218352f7f91STakashi Iwai 	return nums;
2219352f7f91STakashi Iwai }
2220352f7f91STakashi Iwai 
2221352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2222352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2223352f7f91STakashi Iwai  */
2224352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2225352f7f91STakashi Iwai {
2226352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2227352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
22283a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2229352f7f91STakashi Iwai 	int i, n, nums;
2230352f7f91STakashi Iwai 
2231352f7f91STakashi Iwai  again:
2232352f7f91STakashi Iwai 	nums = 0;
22333a65bcdcSTakashi Iwai 	ok_bits = 0;
2234352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2235352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
22363a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2237352f7f91STakashi Iwai 				break;
2238352f7f91STakashi Iwai 		}
22393a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
22403a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
22413a65bcdcSTakashi Iwai 			nums++;
22423a65bcdcSTakashi Iwai 		}
2243352f7f91STakashi Iwai 	}
2244352f7f91STakashi Iwai 
22453a65bcdcSTakashi Iwai 	if (!ok_bits) {
2246352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
2247352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
2248352f7f91STakashi Iwai 			imux->num_items = 1;
2249352f7f91STakashi Iwai 			goto again;
2250352f7f91STakashi Iwai 		}
2251352f7f91STakashi Iwai 
2252352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2253352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2254352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
22553a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2256352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2257352f7f91STakashi Iwai 					break;
2258352f7f91STakashi Iwai 				}
2259352f7f91STakashi Iwai 			}
2260352f7f91STakashi Iwai 		}
2261352f7f91STakashi Iwai 
2262352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2263352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2264352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
22653a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
22663a65bcdcSTakashi Iwai 		nums = 0;
22673a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
22683a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
22693a65bcdcSTakashi Iwai 				continue;
22703a65bcdcSTakashi Iwai 			if (n != nums) {
22713a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2272980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2273980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2274980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
22753a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
22763a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
22773a65bcdcSTakashi Iwai 				}
2278980428ceSTakashi Iwai 			}
22793a65bcdcSTakashi Iwai 			nums++;
22803a65bcdcSTakashi Iwai 		}
2281352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2282352f7f91STakashi Iwai 	}
2283352f7f91STakashi Iwai 
2284352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
2285352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2286352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2287352f7f91STakashi Iwai 	}
2288352f7f91STakashi Iwai 
2289352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2290352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
2291352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
2292352f7f91STakashi Iwai 
22931da177e4SLinus Torvalds 	return 0;
22941da177e4SLinus Torvalds }
22951da177e4SLinus Torvalds 
2296f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
2297f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
2298f3fc0b0bSTakashi Iwai 				int num_adcs, const char *label, int anchor)
2299f3fc0b0bSTakashi Iwai {
2300f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2301f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2302f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
2303f3fc0b0bSTakashi Iwai 	bool imux_added = false;
2304f3fc0b0bSTakashi Iwai 	int c;
2305f3fc0b0bSTakashi Iwai 
2306f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
2307f3fc0b0bSTakashi Iwai 		struct nid_path *path;
2308f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
2309f3fc0b0bSTakashi Iwai 
2310f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
2311f3fc0b0bSTakashi Iwai 			continue;
2312f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
2313f3fc0b0bSTakashi Iwai 		if (!path)
2314f3fc0b0bSTakashi Iwai 			continue;
2315f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
2316f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
2317f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
2318f3fc0b0bSTakashi Iwai 
2319f3fc0b0bSTakashi Iwai 		if (!imux_added) {
2320f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
2321f3fc0b0bSTakashi Iwai 			snd_hda_add_imux_item(imux, label,
2322f3fc0b0bSTakashi Iwai 					      imux->num_items, NULL);
2323f3fc0b0bSTakashi Iwai 			imux_added = true;
2324f3fc0b0bSTakashi Iwai 		}
2325f3fc0b0bSTakashi Iwai 	}
2326f3fc0b0bSTakashi Iwai 
2327f3fc0b0bSTakashi Iwai 	return 0;
2328f3fc0b0bSTakashi Iwai }
2329f3fc0b0bSTakashi Iwai 
23301da177e4SLinus Torvalds /*
2331352f7f91STakashi Iwai  * create playback/capture controls for input pins
23321da177e4SLinus Torvalds  */
2333352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2334a7da6ce5STakashi Iwai {
2335352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2336352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2337352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2338352f7f91STakashi Iwai 	int num_adcs;
2339f3fc0b0bSTakashi Iwai 	int i, err, type_idx = 0;
2340352f7f91STakashi Iwai 	const char *prev_label = NULL;
23412c12c30dSTakashi Iwai 	unsigned int val;
2342a7da6ce5STakashi Iwai 
2343352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2344352f7f91STakashi Iwai 	if (num_adcs < 0)
2345352f7f91STakashi Iwai 		return 0;
2346352f7f91STakashi Iwai 
2347352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2348352f7f91STakashi Iwai 		hda_nid_t pin;
2349352f7f91STakashi Iwai 		const char *label;
2350352f7f91STakashi Iwai 
2351352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2352352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2353352f7f91STakashi Iwai 			continue;
2354352f7f91STakashi Iwai 
2355352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2356352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2357352f7f91STakashi Iwai 			type_idx++;
2358352f7f91STakashi Iwai 		else
2359352f7f91STakashi Iwai 			type_idx = 0;
2360352f7f91STakashi Iwai 		prev_label = label;
2361352f7f91STakashi Iwai 
23622c12c30dSTakashi Iwai 		val = PIN_IN;
23632c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
23642c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
23652c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, false);
23662c12c30dSTakashi Iwai 
2367352f7f91STakashi Iwai 		if (mixer) {
2368352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2369196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2370352f7f91STakashi Iwai 						       label, type_idx, mixer);
2371a7da6ce5STakashi Iwai 				if (err < 0)
2372a7da6ce5STakashi Iwai 					return err;
2373a7da6ce5STakashi Iwai 			}
2374352f7f91STakashi Iwai 		}
2375352f7f91STakashi Iwai 
2376f3fc0b0bSTakashi Iwai 		err = parse_capture_source(codec, pin, num_adcs, label, -mixer);
2377f3fc0b0bSTakashi Iwai 		if (err < 0)
2378f3fc0b0bSTakashi Iwai 			return err;
2379352f7f91STakashi Iwai 	}
2380f3fc0b0bSTakashi Iwai 
2381f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
2382f3fc0b0bSTakashi Iwai 		err = parse_capture_source(codec, mixer, num_adcs,
2383f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
2384f3fc0b0bSTakashi Iwai 		if (err < 0)
2385f3fc0b0bSTakashi Iwai 			return err;
2386352f7f91STakashi Iwai 	}
2387352f7f91STakashi Iwai 
2388a7da6ce5STakashi Iwai 	return 0;
2389a7da6ce5STakashi Iwai }
2390a7da6ce5STakashi Iwai 
23911da177e4SLinus Torvalds 
2392352f7f91STakashi Iwai /*
2393352f7f91STakashi Iwai  * input source mux
2394352f7f91STakashi Iwai  */
2395352f7f91STakashi Iwai 
2396c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
2397c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
2398352f7f91STakashi Iwai {
2399352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2400352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2401352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2402c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
240397ec558aSTakashi Iwai }
2404352f7f91STakashi Iwai 
2405352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2406352f7f91STakashi Iwai 		      unsigned int idx);
2407352f7f91STakashi Iwai 
2408352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2409352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2410352f7f91STakashi Iwai {
2411352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2412352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2413352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2414352f7f91STakashi Iwai }
2415352f7f91STakashi Iwai 
2416352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2417352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2418352f7f91STakashi Iwai {
2419352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2420352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2421352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2422352f7f91STakashi Iwai 
2423352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
24241da177e4SLinus Torvalds 	return 0;
24251da177e4SLinus Torvalds }
24261da177e4SLinus Torvalds 
2427352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2428352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
24291da177e4SLinus Torvalds {
2430352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2431352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2432352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2433352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2434352f7f91STakashi Iwai }
2435352f7f91STakashi Iwai 
2436352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
24371da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2438352f7f91STakashi Iwai 	.name = "Input Source",
2439352f7f91STakashi Iwai 	.info = mux_enum_info,
2440352f7f91STakashi Iwai 	.get = mux_enum_get,
2441352f7f91STakashi Iwai 	.put = mux_enum_put,
24421da177e4SLinus Torvalds };
2443071c73adSTakashi Iwai 
244447d46abbSTakashi Iwai /*
244547d46abbSTakashi Iwai  * capture volume and capture switch ctls
244647d46abbSTakashi Iwai  */
244747d46abbSTakashi Iwai 
2448352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2449352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2450071c73adSTakashi Iwai 
245147d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2452352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2453352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2454352f7f91STakashi Iwai 			  put_call_t func, int type)
2455352f7f91STakashi Iwai {
2456352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2457352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2458352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2459352f7f91STakashi Iwai 	struct nid_path *path;
2460352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2461071c73adSTakashi Iwai 
2462352f7f91STakashi Iwai 	imux = &spec->input_mux;
2463352f7f91STakashi Iwai 	adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2464352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
246547d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
246647d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
246747d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
246847d46abbSTakashi Iwai 	 */
2469352f7f91STakashi Iwai 	codec->cached_write = 1;
2470352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2471c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
2472c697b716STakashi Iwai 		if (!path || !path->ctls[type])
2473352f7f91STakashi Iwai 			continue;
2474352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2475352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2476352f7f91STakashi Iwai 		if (err < 0)
2477352f7f91STakashi Iwai 			goto error;
2478352f7f91STakashi Iwai 	}
2479352f7f91STakashi Iwai  error:
2480352f7f91STakashi Iwai 	codec->cached_write = 0;
2481352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
248247d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2483352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2484352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
2485352f7f91STakashi Iwai 	return err;
2486352f7f91STakashi Iwai }
2487352f7f91STakashi Iwai 
2488352f7f91STakashi Iwai /* capture volume ctl callbacks */
2489352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2490352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2491352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2492352f7f91STakashi Iwai 
2493352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2494352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2495352f7f91STakashi Iwai {
2496352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2497352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2498352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2499352f7f91STakashi Iwai }
2500352f7f91STakashi Iwai 
2501352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2502352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2503352f7f91STakashi Iwai 	.name = "Capture Volume",
2504352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2505352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2506352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2507352f7f91STakashi Iwai 	.info = cap_vol_info,
2508352f7f91STakashi Iwai 	.get = cap_vol_get,
2509352f7f91STakashi Iwai 	.put = cap_vol_put,
2510352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2511352f7f91STakashi Iwai };
2512352f7f91STakashi Iwai 
2513352f7f91STakashi Iwai /* capture switch ctl callbacks */
2514352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2515352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2516352f7f91STakashi Iwai 
2517352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2518352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2519352f7f91STakashi Iwai {
2520352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2521352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2522352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2523352f7f91STakashi Iwai }
2524352f7f91STakashi Iwai 
2525352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2526352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2527352f7f91STakashi Iwai 	.name = "Capture Switch",
2528352f7f91STakashi Iwai 	.info = cap_sw_info,
2529352f7f91STakashi Iwai 	.get = cap_sw_get,
2530352f7f91STakashi Iwai 	.put = cap_sw_put,
2531352f7f91STakashi Iwai };
2532352f7f91STakashi Iwai 
2533352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2534352f7f91STakashi Iwai {
2535352f7f91STakashi Iwai 	hda_nid_t nid;
2536352f7f91STakashi Iwai 	int i, depth;
2537352f7f91STakashi Iwai 
2538352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2539352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2540352f7f91STakashi Iwai 		if (depth >= path->depth)
2541352f7f91STakashi Iwai 			return -EINVAL;
2542352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2543352f7f91STakashi Iwai 		nid = path->path[i];
2544352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2545352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2546352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2547352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2548352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2549352f7f91STakashi Iwai 				int idx = path->idx[i];
2550352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2551352f7f91STakashi Iwai 					idx = 0;
2552352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2553352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2554352f7f91STakashi Iwai 			}
2555352f7f91STakashi Iwai 		}
2556352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2557352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2558352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2559352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2560352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2561352f7f91STakashi Iwai 				int idx = path->idx[i];
2562352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2563352f7f91STakashi Iwai 					idx = 0;
2564352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2565352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2566352f7f91STakashi Iwai 			}
2567352f7f91STakashi Iwai 		}
2568352f7f91STakashi Iwai 	}
2569352f7f91STakashi Iwai 	return 0;
2570352f7f91STakashi Iwai }
2571352f7f91STakashi Iwai 
2572352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2573352f7f91STakashi Iwai {
2574352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2575352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2576352f7f91STakashi Iwai 	unsigned int val;
2577352f7f91STakashi Iwai 	int i;
2578352f7f91STakashi Iwai 
2579352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2580352f7f91STakashi Iwai 		return false;
2581352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2582352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2583352f7f91STakashi Iwai 			continue;
2584352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2585352f7f91STakashi Iwai 			return false;
2586352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2587352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2588352f7f91STakashi Iwai 	}
2589352f7f91STakashi Iwai 	return false;
2590352f7f91STakashi Iwai }
2591352f7f91STakashi Iwai 
2592352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2593352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2594352f7f91STakashi Iwai 			      bool inv_dmic)
2595352f7f91STakashi Iwai {
2596352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2597352f7f91STakashi Iwai 	char tmpname[44];
2598352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2599352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2600352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2601352f7f91STakashi Iwai 	int err;
2602352f7f91STakashi Iwai 
2603352f7f91STakashi Iwai 	if (!ctl)
2604352f7f91STakashi Iwai 		return 0;
2605352f7f91STakashi Iwai 
2606352f7f91STakashi Iwai 	if (label)
2607352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2608352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2609352f7f91STakashi Iwai 	else
2610352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2611352f7f91STakashi Iwai 			 "Capture %s", sfx);
2612352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2613352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2614352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2615352f7f91STakashi Iwai 		return err;
2616352f7f91STakashi Iwai 
2617352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2618352f7f91STakashi Iwai 	if (label)
2619352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2620352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2621352f7f91STakashi Iwai 	else
2622352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2623352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2624352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2625352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2626352f7f91STakashi Iwai }
2627352f7f91STakashi Iwai 
2628352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2629352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2630352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2631352f7f91STakashi Iwai 				     bool inv_dmic)
2632352f7f91STakashi Iwai {
2633352f7f91STakashi Iwai 	int err;
2634352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2635352f7f91STakashi Iwai 	if (err < 0)
2636352f7f91STakashi Iwai 		return err;
2637352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2638071c73adSTakashi Iwai 	if (err < 0)
2639071c73adSTakashi Iwai 		return err;
2640071c73adSTakashi Iwai 	return 0;
26411da177e4SLinus Torvalds }
2642071c73adSTakashi Iwai 
2643352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2644352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2645352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2646352f7f91STakashi Iwai {
2647352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2648352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2649352f7f91STakashi Iwai 
2650352f7f91STakashi Iwai 	if (vol_ctl) {
265112c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2652352f7f91STakashi Iwai 		if (!knew)
2653352f7f91STakashi Iwai 			return -ENOMEM;
2654352f7f91STakashi Iwai 		knew->index = idx;
2655352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2656352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2657352f7f91STakashi Iwai 	}
2658352f7f91STakashi Iwai 	if (sw_ctl) {
265912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2660352f7f91STakashi Iwai 		if (!knew)
2661352f7f91STakashi Iwai 			return -ENOMEM;
2662352f7f91STakashi Iwai 		knew->index = idx;
2663352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2664352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2665352f7f91STakashi Iwai 	}
2666352f7f91STakashi Iwai 	return 0;
2667352f7f91STakashi Iwai }
2668352f7f91STakashi Iwai 
2669352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2670352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2671352f7f91STakashi Iwai {
2672352f7f91STakashi Iwai 	struct nid_path *path;
2673352f7f91STakashi Iwai 	unsigned int ctl;
2674352f7f91STakashi Iwai 	int i;
2675352f7f91STakashi Iwai 
2676c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
2677352f7f91STakashi Iwai 	if (!path)
2678352f7f91STakashi Iwai 		return 0;
2679352f7f91STakashi Iwai 	ctl = path->ctls[type];
2680352f7f91STakashi Iwai 	if (!ctl)
2681352f7f91STakashi Iwai 		return 0;
2682352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2683c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
2684352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2685352f7f91STakashi Iwai 			return 0;
2686352f7f91STakashi Iwai 	}
2687352f7f91STakashi Iwai 	return ctl;
2688352f7f91STakashi Iwai }
2689352f7f91STakashi Iwai 
2690352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2691352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2692352f7f91STakashi Iwai {
2693352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2694352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2695352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2696352f7f91STakashi Iwai 	const char *prev_label = NULL;
2697352f7f91STakashi Iwai 
2698352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2699352f7f91STakashi Iwai 		const char *label;
2700352f7f91STakashi Iwai 		bool inv_dmic;
2701352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
2702352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2703352f7f91STakashi Iwai 			type_idx++;
2704352f7f91STakashi Iwai 		else
2705352f7f91STakashi Iwai 			type_idx = 0;
2706352f7f91STakashi Iwai 		prev_label = label;
2707352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2708352f7f91STakashi Iwai 
2709352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2710352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2711352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2712352f7f91STakashi Iwai 						 inv_dmic);
2713d13bd412STakashi Iwai 			if (err < 0)
2714071c73adSTakashi Iwai 				return err;
2715352f7f91STakashi Iwai 		}
2716352f7f91STakashi Iwai 	}
2717071c73adSTakashi Iwai 	return 0;
2718352f7f91STakashi Iwai }
2719071c73adSTakashi Iwai 
2720352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2721352f7f91STakashi Iwai {
2722352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2723352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2724352f7f91STakashi Iwai 	int i, n, nums, err;
2725352f7f91STakashi Iwai 
2726352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2727352f7f91STakashi Iwai 		nums = 1;
2728352f7f91STakashi Iwai 	else
2729352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2730352f7f91STakashi Iwai 
2731352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2732352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2733624d914dSTakashi Iwai 		const char *name;
2734624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2735624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2736352f7f91STakashi Iwai 		if (!knew)
2737352f7f91STakashi Iwai 			return -ENOMEM;
2738352f7f91STakashi Iwai 		knew->count = nums;
2739352f7f91STakashi Iwai 	}
2740352f7f91STakashi Iwai 
2741352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2742352f7f91STakashi Iwai 		bool multi = false;
2743352f7f91STakashi Iwai 		bool inv_dmic = false;
2744352f7f91STakashi Iwai 		int vol, sw;
2745352f7f91STakashi Iwai 
2746352f7f91STakashi Iwai 		vol = sw = 0;
2747352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2748352f7f91STakashi Iwai 			struct nid_path *path;
2749c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
2750352f7f91STakashi Iwai 			if (!path)
2751352f7f91STakashi Iwai 				continue;
2752352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2753352f7f91STakashi Iwai 			if (!vol)
2754352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
2755352f7f91STakashi Iwai 			else if (vol != path->ctls[NID_PATH_VOL_CTL])
2756352f7f91STakashi Iwai 				multi = true;
2757352f7f91STakashi Iwai 			if (!sw)
2758352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
2759352f7f91STakashi Iwai 			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
2760352f7f91STakashi Iwai 				multi = true;
2761352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2762352f7f91STakashi Iwai 				inv_dmic = true;
2763352f7f91STakashi Iwai 		}
2764352f7f91STakashi Iwai 
2765352f7f91STakashi Iwai 		if (!multi)
2766352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2767352f7f91STakashi Iwai 							inv_dmic);
2768352f7f91STakashi Iwai 		else if (!spec->multi_cap_vol)
2769352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2770352f7f91STakashi Iwai 		else
2771352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
2772d13bd412STakashi Iwai 		if (err < 0)
2773071c73adSTakashi Iwai 			return err;
2774071c73adSTakashi Iwai 	}
2775071c73adSTakashi Iwai 
27761da177e4SLinus Torvalds 	return 0;
27771da177e4SLinus Torvalds }
27781da177e4SLinus Torvalds 
2779352f7f91STakashi Iwai /*
2780352f7f91STakashi Iwai  * add mic boosts if needed
2781352f7f91STakashi Iwai  */
2782352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
2783352f7f91STakashi Iwai {
2784352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2785352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2786352f7f91STakashi Iwai 	int i, err;
2787352f7f91STakashi Iwai 	int type_idx = 0;
2788352f7f91STakashi Iwai 	hda_nid_t nid;
2789352f7f91STakashi Iwai 	const char *prev_label = NULL;
2790352f7f91STakashi Iwai 
2791352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2792352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
2793352f7f91STakashi Iwai 			break;
2794352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
2795352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
2796352f7f91STakashi Iwai 			const char *label;
27975abd4888STakashi Iwai 			char boost_label[44];
2798352f7f91STakashi Iwai 			struct nid_path *path;
2799352f7f91STakashi Iwai 			unsigned int val;
2800352f7f91STakashi Iwai 
2801352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
2802352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
2803352f7f91STakashi Iwai 				type_idx++;
2804352f7f91STakashi Iwai 			else
2805352f7f91STakashi Iwai 				type_idx = 0;
2806352f7f91STakashi Iwai 			prev_label = label;
2807352f7f91STakashi Iwai 
2808352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
2809352f7f91STakashi Iwai 				 "%s Boost Volume", label);
2810352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
2811352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
2812352f7f91STakashi Iwai 					  boost_label, type_idx, val);
2813352f7f91STakashi Iwai 			if (err < 0)
2814352f7f91STakashi Iwai 				return err;
2815352f7f91STakashi Iwai 
2816352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
2817352f7f91STakashi Iwai 			if (path)
2818352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
2819352f7f91STakashi Iwai 		}
2820352f7f91STakashi Iwai 	}
2821352f7f91STakashi Iwai 	return 0;
2822352f7f91STakashi Iwai }
2823352f7f91STakashi Iwai 
2824352f7f91STakashi Iwai /*
2825352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
2826352f7f91STakashi Iwai  */
2827352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
2828352f7f91STakashi Iwai {
2829352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28300c8c0f56STakashi Iwai 	struct nid_path *path;
2831352f7f91STakashi Iwai 	int i, nums;
28322c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
2833352f7f91STakashi Iwai 
2834352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
2835352f7f91STakashi Iwai 	nums = 0;
2836352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
28372c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
2838352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
2839352f7f91STakashi Iwai 		if (!dig_nid)
2840352f7f91STakashi Iwai 			continue;
28413ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
28420c8c0f56STakashi Iwai 		if (!path)
2843352f7f91STakashi Iwai 			continue;
28440c8c0f56STakashi Iwai 		print_nid_path("digout", path);
2845e1284af7STakashi Iwai 		path->active = true;
2846196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
28472c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
2848352f7f91STakashi Iwai 		if (!nums) {
2849352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
2850352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
2851352f7f91STakashi Iwai 		} else {
2852352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2853352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2854352f7f91STakashi Iwai 			break;
2855352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
2856352f7f91STakashi Iwai 		}
2857352f7f91STakashi Iwai 		nums++;
2858352f7f91STakashi Iwai 	}
2859352f7f91STakashi Iwai 
2860352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
28612c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
2862352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
2863352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2864352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
2865352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2866352f7f91STakashi Iwai 				continue;
2867352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
2868352f7f91STakashi Iwai 				continue;
28692c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
2870352f7f91STakashi Iwai 			if (path) {
28710c8c0f56STakashi Iwai 				print_nid_path("digin", path);
2872352f7f91STakashi Iwai 				path->active = true;
2873352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
28742430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
28752c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
2876352f7f91STakashi Iwai 				break;
2877352f7f91STakashi Iwai 			}
2878352f7f91STakashi Iwai 		}
2879352f7f91STakashi Iwai 	}
2880352f7f91STakashi Iwai }
2881352f7f91STakashi Iwai 
28821da177e4SLinus Torvalds 
28831da177e4SLinus Torvalds /*
2884352f7f91STakashi Iwai  * input MUX handling
28851da177e4SLinus Torvalds  */
28861da177e4SLinus Torvalds 
2887352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
2888352f7f91STakashi Iwai 
2889352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
2890352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2891352f7f91STakashi Iwai 		      unsigned int idx)
2892352f7f91STakashi Iwai {
2893352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2894352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2895352f7f91STakashi Iwai 	struct nid_path *path;
2896352f7f91STakashi Iwai 
2897352f7f91STakashi Iwai 	imux = &spec->input_mux;
2898352f7f91STakashi Iwai 	if (!imux->num_items)
28991da177e4SLinus Torvalds 		return 0;
29001da177e4SLinus Torvalds 
2901352f7f91STakashi Iwai 	if (idx >= imux->num_items)
2902352f7f91STakashi Iwai 		idx = imux->num_items - 1;
2903352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
2904352f7f91STakashi Iwai 		return 0;
2905352f7f91STakashi Iwai 
2906c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
2907352f7f91STakashi Iwai 	if (!path)
2908352f7f91STakashi Iwai 		return 0;
2909352f7f91STakashi Iwai 	if (path->active)
2910352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
2911352f7f91STakashi Iwai 
2912352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
2913352f7f91STakashi Iwai 
2914352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
2915352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
2916352f7f91STakashi Iwai 
2917352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2918352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
2919352f7f91STakashi Iwai 
2920c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
2921352f7f91STakashi Iwai 	if (!path)
2922352f7f91STakashi Iwai 		return 0;
2923352f7f91STakashi Iwai 	if (path->active)
2924352f7f91STakashi Iwai 		return 0;
2925352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
2926352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
2927352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
29281da177e4SLinus Torvalds 	return 1;
29291da177e4SLinus Torvalds }
29301da177e4SLinus Torvalds 
29311da177e4SLinus Torvalds 
29321da177e4SLinus Torvalds /*
2933352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
29341da177e4SLinus Torvalds  */
2935352f7f91STakashi Iwai 
2936352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
2937352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
29381da177e4SLinus Torvalds {
2939352f7f91STakashi Iwai 	int i, present = 0;
29401da177e4SLinus Torvalds 
2941352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2942352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2943352f7f91STakashi Iwai 		if (!nid)
2944352f7f91STakashi Iwai 			break;
29450b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
29460b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
29470b4df931STakashi Iwai 			continue;
2948352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
29491da177e4SLinus Torvalds 	}
2950352f7f91STakashi Iwai 	return present;
29511da177e4SLinus Torvalds }
29521da177e4SLinus Torvalds 
2953352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
2954352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
29552c12c30dSTakashi Iwai 			bool mute)
29561da177e4SLinus Torvalds {
2957352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2958352f7f91STakashi Iwai 	int i;
29591da177e4SLinus Torvalds 
2960352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2961352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2962352f7f91STakashi Iwai 		unsigned int val;
2963352f7f91STakashi Iwai 		if (!nid)
2964352f7f91STakashi Iwai 			break;
2965352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
2966352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
2967352f7f91STakashi Iwai 		 */
29682c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
29692c12c30dSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
29702c12c30dSTakashi Iwai 		else
2971352f7f91STakashi Iwai 			val = 0;
29722c12c30dSTakashi Iwai 		if (!mute)
29732c12c30dSTakashi Iwai 			val |= snd_hda_codec_get_pin_target(codec, nid);
29742c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
29752c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
29762c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
29772c12c30dSTakashi Iwai 		 * init / resume again
29782c12c30dSTakashi Iwai 		 */
29792c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
2980d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
2981352f7f91STakashi Iwai 	}
2982352f7f91STakashi Iwai }
29831da177e4SLinus Torvalds 
2984352f7f91STakashi Iwai /* Toggle outputs muting */
29855d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
2986352f7f91STakashi Iwai {
2987352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2988352f7f91STakashi Iwai 	int on;
2989352f7f91STakashi Iwai 
2990352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
2991352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
2992352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
2993352f7f91STakashi Iwai 	 */
2994352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
2995352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
29962c12c30dSTakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute);
2997352f7f91STakashi Iwai 
2998352f7f91STakashi Iwai 	if (!spec->automute_speaker)
2999352f7f91STakashi Iwai 		on = 0;
3000352f7f91STakashi Iwai 	else
3001352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3002352f7f91STakashi Iwai 	on |= spec->master_mute;
3003352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
30042c12c30dSTakashi Iwai 		    spec->autocfg.speaker_pins, on);
3005352f7f91STakashi Iwai 
3006352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3007352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3008352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3009352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3010352f7f91STakashi Iwai 		return;
3011352f7f91STakashi Iwai 	if (!spec->automute_lo)
3012352f7f91STakashi Iwai 		on = 0;
3013352f7f91STakashi Iwai 	else
3014352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3015352f7f91STakashi Iwai 	on |= spec->master_mute;
3016352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
30172c12c30dSTakashi Iwai 		    spec->autocfg.line_out_pins, on);
3018352f7f91STakashi Iwai }
30195d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3020352f7f91STakashi Iwai 
3021352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3022352f7f91STakashi Iwai {
3023352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3024352f7f91STakashi Iwai 	if (spec->automute_hook)
3025352f7f91STakashi Iwai 		spec->automute_hook(codec);
3026352f7f91STakashi Iwai 	else
30275d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
3028352f7f91STakashi Iwai }
3029352f7f91STakashi Iwai 
3030352f7f91STakashi Iwai /* standard HP-automute helper */
30315d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3032352f7f91STakashi Iwai {
3033352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3034352f7f91STakashi Iwai 
3035352f7f91STakashi Iwai 	spec->hp_jack_present =
3036352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3037352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
3038352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3039352f7f91STakashi Iwai 		return;
3040352f7f91STakashi Iwai 	call_update_outputs(codec);
3041352f7f91STakashi Iwai }
30425d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3043352f7f91STakashi Iwai 
3044352f7f91STakashi Iwai /* standard line-out-automute helper */
30455d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3046352f7f91STakashi Iwai {
3047352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3048352f7f91STakashi Iwai 
3049352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3050352f7f91STakashi Iwai 		return;
3051352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3052352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3053352f7f91STakashi Iwai 		return;
3054352f7f91STakashi Iwai 
3055352f7f91STakashi Iwai 	spec->line_jack_present =
3056352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3057352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3058352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3059352f7f91STakashi Iwai 		return;
3060352f7f91STakashi Iwai 	call_update_outputs(codec);
3061352f7f91STakashi Iwai }
30625d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3063352f7f91STakashi Iwai 
3064352f7f91STakashi Iwai /* standard mic auto-switch helper */
30655d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3066352f7f91STakashi Iwai {
3067352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3068352f7f91STakashi Iwai 	int i;
3069352f7f91STakashi Iwai 
3070352f7f91STakashi Iwai 	if (!spec->auto_mic)
3071352f7f91STakashi Iwai 		return;
3072352f7f91STakashi Iwai 
3073352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
30740b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
30750b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
30760b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
30770b4df931STakashi Iwai 			continue;
30780b4df931STakashi Iwai 		if (snd_hda_jack_detect(codec, pin)) {
3079352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3080352f7f91STakashi Iwai 			return;
3081352f7f91STakashi Iwai 		}
3082352f7f91STakashi Iwai 	}
3083352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
30841da177e4SLinus Torvalds }
30855d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
30861da177e4SLinus Torvalds 
30871da177e4SLinus Torvalds /*
3088352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
30891da177e4SLinus Torvalds  */
3090352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
3091352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
3092352f7f91STakashi Iwai {
3093352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3094352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3095352f7f91STakashi Iwai 	static const char * const texts3[] = {
3096352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
30971da177e4SLinus Torvalds 	};
30981da177e4SLinus Torvalds 
3099352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
3100352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
3101352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
3102352f7f91STakashi Iwai }
3103352f7f91STakashi Iwai 
3104352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
3105352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3106352f7f91STakashi Iwai {
3107352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3108352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3109352f7f91STakashi Iwai 	unsigned int val = 0;
3110352f7f91STakashi Iwai 	if (spec->automute_speaker)
3111352f7f91STakashi Iwai 		val++;
3112352f7f91STakashi Iwai 	if (spec->automute_lo)
3113352f7f91STakashi Iwai 		val++;
3114352f7f91STakashi Iwai 
3115352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
3116352f7f91STakashi Iwai 	return 0;
3117352f7f91STakashi Iwai }
3118352f7f91STakashi Iwai 
3119352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
3120352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3121352f7f91STakashi Iwai {
3122352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3123352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3124352f7f91STakashi Iwai 
3125352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
3126352f7f91STakashi Iwai 	case 0:
3127352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
3128352f7f91STakashi Iwai 			return 0;
3129352f7f91STakashi Iwai 		spec->automute_speaker = 0;
3130352f7f91STakashi Iwai 		spec->automute_lo = 0;
3131352f7f91STakashi Iwai 		break;
3132352f7f91STakashi Iwai 	case 1:
3133352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
3134352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
3135352f7f91STakashi Iwai 				return 0;
3136352f7f91STakashi Iwai 			spec->automute_speaker = 1;
3137352f7f91STakashi Iwai 			spec->automute_lo = 0;
3138352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
3139352f7f91STakashi Iwai 			if (spec->automute_lo)
3140352f7f91STakashi Iwai 				return 0;
3141352f7f91STakashi Iwai 			spec->automute_lo = 1;
3142352f7f91STakashi Iwai 		} else
3143352f7f91STakashi Iwai 			return -EINVAL;
3144352f7f91STakashi Iwai 		break;
3145352f7f91STakashi Iwai 	case 2:
3146352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
3147352f7f91STakashi Iwai 			return -EINVAL;
3148352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
3149352f7f91STakashi Iwai 			return 0;
3150352f7f91STakashi Iwai 		spec->automute_speaker = 1;
3151352f7f91STakashi Iwai 		spec->automute_lo = 1;
3152352f7f91STakashi Iwai 		break;
3153352f7f91STakashi Iwai 	default:
3154352f7f91STakashi Iwai 		return -EINVAL;
3155352f7f91STakashi Iwai 	}
3156352f7f91STakashi Iwai 	call_update_outputs(codec);
3157352f7f91STakashi Iwai 	return 1;
3158352f7f91STakashi Iwai }
3159352f7f91STakashi Iwai 
3160352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
3161352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3162352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
3163352f7f91STakashi Iwai 	.info = automute_mode_info,
3164352f7f91STakashi Iwai 	.get = automute_mode_get,
3165352f7f91STakashi Iwai 	.put = automute_mode_put,
3166352f7f91STakashi Iwai };
3167352f7f91STakashi Iwai 
3168352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
3169352f7f91STakashi Iwai {
3170352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3171352f7f91STakashi Iwai 
317212c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
3173352f7f91STakashi Iwai 		return -ENOMEM;
3174352f7f91STakashi Iwai 	return 0;
3175352f7f91STakashi Iwai }
3176352f7f91STakashi Iwai 
3177352f7f91STakashi Iwai /*
3178352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
3179352f7f91STakashi Iwai  * Set up appropriately if really supported
3180352f7f91STakashi Iwai  */
3181352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
3182352f7f91STakashi Iwai {
3183352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3184352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3185352f7f91STakashi Iwai 	int present = 0;
3186352f7f91STakashi Iwai 	int i, err;
3187352f7f91STakashi Iwai 
3188352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
3189352f7f91STakashi Iwai 		present++;
3190352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
3191352f7f91STakashi Iwai 		present++;
3192352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
3193352f7f91STakashi Iwai 		present++;
3194352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
3195352f7f91STakashi Iwai 		return 0;
3196352f7f91STakashi Iwai 
3197352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
3198352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
3199352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3200352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3201352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3202352f7f91STakashi Iwai 	}
3203352f7f91STakashi Iwai 
3204352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
3205352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
3206352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
3207352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
3208352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
3209352f7f91STakashi Iwai 	}
3210352f7f91STakashi Iwai 
3211352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
3212352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
3213352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
3214352f7f91STakashi Iwai 			continue;
3215352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
3216352f7f91STakashi Iwai 			    nid);
3217352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
32182e03e952STakashi Iwai 						    spec->hp_automute_hook ?
32192e03e952STakashi Iwai 						    spec->hp_automute_hook :
32205d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
3221352f7f91STakashi Iwai 		spec->detect_hp = 1;
3222352f7f91STakashi Iwai 	}
3223352f7f91STakashi Iwai 
3224352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
3225352f7f91STakashi Iwai 		if (cfg->speaker_outs)
3226352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
3227352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
3228352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
3229352f7f91STakashi Iwai 					continue;
3230352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
3231352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
3232352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
32332e03e952STakashi Iwai 								    spec->line_automute_hook ?
32342e03e952STakashi Iwai 								    spec->line_automute_hook :
32355d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
3236352f7f91STakashi Iwai 				spec->detect_lo = 1;
3237352f7f91STakashi Iwai 			}
3238352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
3239352f7f91STakashi Iwai 	}
3240352f7f91STakashi Iwai 
3241352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
3242352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
3243352f7f91STakashi Iwai 
3244352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
3245352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
3246352f7f91STakashi Iwai 
3247352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
3248352f7f91STakashi Iwai 		/* create a control for automute mode */
3249352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
3250352f7f91STakashi Iwai 		if (err < 0)
3251352f7f91STakashi Iwai 			return err;
3252352f7f91STakashi Iwai 	}
3253352f7f91STakashi Iwai 	return 0;
3254352f7f91STakashi Iwai }
3255352f7f91STakashi Iwai 
3256352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
3257352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
3258352f7f91STakashi Iwai {
3259352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3260352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3261352f7f91STakashi Iwai 	int i;
3262352f7f91STakashi Iwai 
3263352f7f91STakashi Iwai 	imux = &spec->input_mux;
3264352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
3265352f7f91STakashi Iwai 		spec->am_entry[i].idx =
3266352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
3267352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
3268352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
3269352f7f91STakashi Iwai 			return false; /* no corresponding imux */
3270352f7f91STakashi Iwai 	}
3271352f7f91STakashi Iwai 
3272352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
3273352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
3274352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
3275352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
3276352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
32772e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
32782e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
32795d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
3280352f7f91STakashi Iwai 	return true;
3281352f7f91STakashi Iwai }
3282352f7f91STakashi Iwai 
3283352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
3284352f7f91STakashi Iwai {
3285352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
3286352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
3287352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
3288352f7f91STakashi Iwai }
3289352f7f91STakashi Iwai 
3290352f7f91STakashi Iwai /*
3291352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
3292352f7f91STakashi Iwai  * Set up if really supported
3293352f7f91STakashi Iwai  */
3294352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
3295352f7f91STakashi Iwai {
3296352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3297352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3298352f7f91STakashi Iwai 	unsigned int types;
3299352f7f91STakashi Iwai 	int i, num_pins;
3300352f7f91STakashi Iwai 
3301d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
3302d12daf6fSTakashi Iwai 		return 0;
3303d12daf6fSTakashi Iwai 
3304352f7f91STakashi Iwai 	types = 0;
3305352f7f91STakashi Iwai 	num_pins = 0;
3306352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3307352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3308352f7f91STakashi Iwai 		unsigned int attr;
3309352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3310352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3311352f7f91STakashi Iwai 		if (types & (1 << attr))
3312352f7f91STakashi Iwai 			return 0; /* already occupied */
3313352f7f91STakashi Iwai 		switch (attr) {
3314352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3315352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3316352f7f91STakashi Iwai 				return 0; /* invalid type */
3317352f7f91STakashi Iwai 			break;
3318352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3319352f7f91STakashi Iwai 			return 0; /* invalid entry */
3320352f7f91STakashi Iwai 		default:
3321352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3322352f7f91STakashi Iwai 				return 0; /* invalid type */
3323352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3324352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3325352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3326352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3327352f7f91STakashi Iwai 				return 0; /* no unsol support */
3328352f7f91STakashi Iwai 			break;
3329352f7f91STakashi Iwai 		}
3330352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3331352f7f91STakashi Iwai 			return 0;
3332352f7f91STakashi Iwai 		types |= (1 << attr);
3333352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3334352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3335352f7f91STakashi Iwai 		num_pins++;
3336352f7f91STakashi Iwai 	}
3337352f7f91STakashi Iwai 
3338352f7f91STakashi Iwai 	if (num_pins < 2)
3339352f7f91STakashi Iwai 		return 0;
3340352f7f91STakashi Iwai 
3341352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3342352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3343352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3344352f7f91STakashi Iwai 	 */
3345352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3346352f7f91STakashi Iwai 	     compare_attr, NULL);
3347352f7f91STakashi Iwai 
3348352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3349352f7f91STakashi Iwai 		return 0;
3350352f7f91STakashi Iwai 
3351352f7f91STakashi Iwai 	spec->auto_mic = 1;
3352352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3353352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3354352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3355352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3356352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3357352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3358352f7f91STakashi Iwai 
3359352f7f91STakashi Iwai 	return 0;
3360352f7f91STakashi Iwai }
3361352f7f91STakashi Iwai 
3362352f7f91STakashi Iwai 
33639eb413e5STakashi Iwai /*
33649eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
33659eb413e5STakashi Iwai  *
33669eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3367352f7f91STakashi Iwai  * or a negative error code
3368352f7f91STakashi Iwai  */
3369352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
33709eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3371352f7f91STakashi Iwai {
3372352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3373352f7f91STakashi Iwai 	int err;
3374352f7f91STakashi Iwai 
3375*1c70a583STakashi Iwai 	parse_user_hints(codec);
3376*1c70a583STakashi Iwai 
33779eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
33789eb413e5STakashi Iwai 		spec->autocfg = *cfg;
33799eb413e5STakashi Iwai 		cfg = &spec->autocfg;
33809eb413e5STakashi Iwai 	}
33819eb413e5STakashi Iwai 
3382352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3383352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3384352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3385352f7f91STakashi Iwai 			spec->no_analog = 1;
3386352f7f91STakashi Iwai 			goto dig_only;
3387352f7f91STakashi Iwai 		}
3388352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3389352f7f91STakashi Iwai 	}
3390352f7f91STakashi Iwai 
3391352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3392352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3393352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3394352f7f91STakashi Iwai 		/* use HP as primary out */
3395352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3396352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3397352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3398352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3399352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3400352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3401352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3402352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3403352f7f91STakashi Iwai 	}
3404352f7f91STakashi Iwai 
3405352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3406352f7f91STakashi Iwai 	if (err < 0)
3407352f7f91STakashi Iwai 		return err;
3408352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3409352f7f91STakashi Iwai 	if (err < 0)
3410352f7f91STakashi Iwai 		return err;
3411352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3412352f7f91STakashi Iwai 	if (err < 0)
3413352f7f91STakashi Iwai 		return err;
3414352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3415352f7f91STakashi Iwai 	if (err < 0)
3416352f7f91STakashi Iwai 		return err;
3417352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3418352f7f91STakashi Iwai 	if (err < 0)
3419352f7f91STakashi Iwai 		return err;
342038cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
342138cf6f1aSTakashi Iwai 	if (err < 0)
342238cf6f1aSTakashi Iwai 		return err;
3423c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3424c30aa7b2STakashi Iwai 	if (err < 0)
3425c30aa7b2STakashi Iwai 		return err;
3426352f7f91STakashi Iwai 	err = create_shared_input(codec);
3427352f7f91STakashi Iwai 	if (err < 0)
3428352f7f91STakashi Iwai 		return err;
3429352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3430352f7f91STakashi Iwai 	if (err < 0)
3431352f7f91STakashi Iwai 		return err;
3432352f7f91STakashi Iwai 
3433a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
3434a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
3435a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
3436a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3437a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
3438a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3439a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3440a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
3441352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
3442352f7f91STakashi Iwai 					  spec->const_channel_count);
3443352f7f91STakashi Iwai 
3444352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3445352f7f91STakashi Iwai 	if (err < 0)
3446352f7f91STakashi Iwai 		return err;
3447352f7f91STakashi Iwai 
3448352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3449352f7f91STakashi Iwai 	if (err < 0)
3450352f7f91STakashi Iwai 		return err;
3451352f7f91STakashi Iwai 
3452352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3453352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3454352f7f91STakashi Iwai 		if (err < 0)
3455352f7f91STakashi Iwai 			return err;
3456352f7f91STakashi Iwai 	}
3457352f7f91STakashi Iwai 
3458352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3459352f7f91STakashi Iwai 	if (err < 0)
3460352f7f91STakashi Iwai 		return err;
3461352f7f91STakashi Iwai 
3462352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3463352f7f91STakashi Iwai 	if (err < 0)
3464352f7f91STakashi Iwai 		return err;
3465352f7f91STakashi Iwai 
3466978e77e7STakashi Iwai 	if (spec->add_out_jack_modes) {
3467978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3468978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
3469978e77e7STakashi Iwai 						    cfg->line_out_pins);
3470978e77e7STakashi Iwai 			if (err < 0)
3471978e77e7STakashi Iwai 				return err;
3472978e77e7STakashi Iwai 		}
3473978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
3474978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
3475978e77e7STakashi Iwai 						    cfg->hp_pins);
3476978e77e7STakashi Iwai 			if (err < 0)
3477978e77e7STakashi Iwai 				return err;
3478978e77e7STakashi Iwai 		}
3479978e77e7STakashi Iwai 	}
3480978e77e7STakashi Iwai 
3481352f7f91STakashi Iwai  dig_only:
3482352f7f91STakashi Iwai 	parse_digital(codec);
3483352f7f91STakashi Iwai 
3484352f7f91STakashi Iwai 	return 1;
3485352f7f91STakashi Iwai }
3486352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3487352f7f91STakashi Iwai 
3488352f7f91STakashi Iwai 
3489352f7f91STakashi Iwai /*
3490352f7f91STakashi Iwai  * Build control elements
3491352f7f91STakashi Iwai  */
3492352f7f91STakashi Iwai 
3493352f7f91STakashi Iwai /* slave controls for virtual master */
3494352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3495352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3496352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3497352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3498ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3499ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3500ee79c69aSTakashi Iwai 	"Headphone Side",
3501352f7f91STakashi Iwai 	NULL,
3502352f7f91STakashi Iwai };
3503352f7f91STakashi Iwai 
3504352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3505352f7f91STakashi Iwai {
3506352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3507352f7f91STakashi Iwai 	int err;
3508352f7f91STakashi Iwai 
350936502d02STakashi Iwai 	if (spec->kctls.used) {
3510352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3511352f7f91STakashi Iwai 		if (err < 0)
3512352f7f91STakashi Iwai 			return err;
351336502d02STakashi Iwai 	}
3514352f7f91STakashi Iwai 
3515352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3516352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3517352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3518352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3519352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3520352f7f91STakashi Iwai 		if (err < 0)
3521352f7f91STakashi Iwai 			return err;
3522352f7f91STakashi Iwai 		if (!spec->no_analog) {
3523352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3524352f7f91STakashi Iwai 							    &spec->multiout);
3525352f7f91STakashi Iwai 			if (err < 0)
3526352f7f91STakashi Iwai 				return err;
3527352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3528352f7f91STakashi Iwai 		}
3529352f7f91STakashi Iwai 	}
3530352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3531352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3532352f7f91STakashi Iwai 		if (err < 0)
3533352f7f91STakashi Iwai 			return err;
3534352f7f91STakashi Iwai 	}
3535352f7f91STakashi Iwai 
3536352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3537352f7f91STakashi Iwai 	if (!spec->no_analog &&
3538352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3539352f7f91STakashi Iwai 		unsigned int vmaster_tlv[4];
3540352f7f91STakashi Iwai 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
3541352f7f91STakashi Iwai 					HDA_OUTPUT, vmaster_tlv);
3542352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
3543352f7f91STakashi Iwai 					  vmaster_tlv, slave_pfxs,
3544352f7f91STakashi Iwai 					  "Playback Volume");
3545352f7f91STakashi Iwai 		if (err < 0)
3546352f7f91STakashi Iwai 			return err;
3547352f7f91STakashi Iwai 	}
3548352f7f91STakashi Iwai 	if (!spec->no_analog &&
3549352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3550352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3551352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3552352f7f91STakashi Iwai 					    "Playback Switch",
3553352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3554352f7f91STakashi Iwai 		if (err < 0)
3555352f7f91STakashi Iwai 			return err;
3556352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3557fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3558fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3559352f7f91STakashi Iwai 	}
3560352f7f91STakashi Iwai 
3561352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3562352f7f91STakashi Iwai 
3563352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3564352f7f91STakashi Iwai 		int err;
3565352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3566352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3567352f7f91STakashi Iwai 		if (err < 0)
3568352f7f91STakashi Iwai 			return err;
3569352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3570352f7f91STakashi Iwai 		if (err < 0)
3571352f7f91STakashi Iwai 			return err;
3572352f7f91STakashi Iwai 	}
3573352f7f91STakashi Iwai 
3574352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3575352f7f91STakashi Iwai 	if (err < 0)
3576352f7f91STakashi Iwai 		return err;
3577352f7f91STakashi Iwai 
3578352f7f91STakashi Iwai 	return 0;
3579352f7f91STakashi Iwai }
3580352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3581352f7f91STakashi Iwai 
3582352f7f91STakashi Iwai 
3583352f7f91STakashi Iwai /*
3584352f7f91STakashi Iwai  * PCM definitions
3585352f7f91STakashi Iwai  */
3586352f7f91STakashi Iwai 
3587e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
3588e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
3589e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
3590e6b85f3cSTakashi Iwai 				   int action)
3591e6b85f3cSTakashi Iwai {
3592e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3593e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
3594e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
3595e6b85f3cSTakashi Iwai }
3596e6b85f3cSTakashi Iwai 
3597352f7f91STakashi Iwai /*
3598352f7f91STakashi Iwai  * Analog playback callbacks
3599352f7f91STakashi Iwai  */
3600352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3601352f7f91STakashi Iwai 			     struct hda_codec *codec,
3602352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3603352f7f91STakashi Iwai {
3604352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
360538cf6f1aSTakashi Iwai 	int err;
360638cf6f1aSTakashi Iwai 
360738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
360838cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
360938cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3610352f7f91STakashi Iwai 					     hinfo);
3611e6b85f3cSTakashi Iwai 	if (!err) {
361238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
3613e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3614e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
3615e6b85f3cSTakashi Iwai 	}
361638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
361738cf6f1aSTakashi Iwai 	return err;
3618352f7f91STakashi Iwai }
3619352f7f91STakashi Iwai 
3620352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
362197ec558aSTakashi Iwai 				struct hda_codec *codec,
362297ec558aSTakashi Iwai 				unsigned int stream_tag,
362397ec558aSTakashi Iwai 				unsigned int format,
362497ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
362597ec558aSTakashi Iwai {
3626352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3627e6b85f3cSTakashi Iwai 	int err;
3628e6b85f3cSTakashi Iwai 
3629e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3630352f7f91STakashi Iwai 					       stream_tag, format, substream);
3631e6b85f3cSTakashi Iwai 	if (!err)
3632e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3633e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
3634e6b85f3cSTakashi Iwai 	return err;
3635352f7f91STakashi Iwai }
363697ec558aSTakashi Iwai 
3637352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3638352f7f91STakashi Iwai 				struct hda_codec *codec,
3639352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3640352f7f91STakashi Iwai {
3641352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3642e6b85f3cSTakashi Iwai 	int err;
3643e6b85f3cSTakashi Iwai 
3644e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3645e6b85f3cSTakashi Iwai 	if (!err)
3646e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3647e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
3648e6b85f3cSTakashi Iwai 	return err;
3649352f7f91STakashi Iwai }
3650352f7f91STakashi Iwai 
365138cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
365238cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
365338cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
365438cf6f1aSTakashi Iwai {
365538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
365638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
365738cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
3658e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3659e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
366038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
366138cf6f1aSTakashi Iwai 	return 0;
366238cf6f1aSTakashi Iwai }
366338cf6f1aSTakashi Iwai 
366438cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
366538cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
366638cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
366738cf6f1aSTakashi Iwai {
366838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
366938cf6f1aSTakashi Iwai 	int err = 0;
367038cf6f1aSTakashi Iwai 
367138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
367238cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
367338cf6f1aSTakashi Iwai 		err = -EBUSY;
367438cf6f1aSTakashi Iwai 	else
367538cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
3676e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3677e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
367838cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
367938cf6f1aSTakashi Iwai 	return err;
368038cf6f1aSTakashi Iwai }
368138cf6f1aSTakashi Iwai 
368238cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
368338cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
368438cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
368538cf6f1aSTakashi Iwai {
368638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
368738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
368838cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
3689e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3690e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
369138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
369238cf6f1aSTakashi Iwai 	return 0;
369338cf6f1aSTakashi Iwai }
369438cf6f1aSTakashi Iwai 
3695e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3696e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
3697e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
3698e6b85f3cSTakashi Iwai 				    unsigned int format,
3699e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
3700e6b85f3cSTakashi Iwai {
3701e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3702e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3703e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
3704e6b85f3cSTakashi Iwai 	return 0;
3705e6b85f3cSTakashi Iwai }
3706e6b85f3cSTakashi Iwai 
3707e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3708e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
3709e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
3710e6b85f3cSTakashi Iwai {
3711e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
3712e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3713e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
3714e6b85f3cSTakashi Iwai 	return 0;
3715e6b85f3cSTakashi Iwai }
3716e6b85f3cSTakashi Iwai 
3717352f7f91STakashi Iwai /*
3718352f7f91STakashi Iwai  * Digital out
3719352f7f91STakashi Iwai  */
3720352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3721352f7f91STakashi Iwai 				 struct hda_codec *codec,
3722352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
3723352f7f91STakashi Iwai {
3724352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3725352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3726352f7f91STakashi Iwai }
3727352f7f91STakashi Iwai 
3728352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3729352f7f91STakashi Iwai 				    struct hda_codec *codec,
3730352f7f91STakashi Iwai 				    unsigned int stream_tag,
3731352f7f91STakashi Iwai 				    unsigned int format,
3732352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3733352f7f91STakashi Iwai {
3734352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3735352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3736352f7f91STakashi Iwai 					     stream_tag, format, substream);
3737352f7f91STakashi Iwai }
3738352f7f91STakashi Iwai 
3739352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3740352f7f91STakashi Iwai 				    struct hda_codec *codec,
3741352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3742352f7f91STakashi Iwai {
3743352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3744352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3745352f7f91STakashi Iwai }
3746352f7f91STakashi Iwai 
3747352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3748352f7f91STakashi Iwai 				  struct hda_codec *codec,
3749352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
3750352f7f91STakashi Iwai {
3751352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3752352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3753352f7f91STakashi Iwai }
3754352f7f91STakashi Iwai 
3755352f7f91STakashi Iwai /*
3756352f7f91STakashi Iwai  * Analog capture
3757352f7f91STakashi Iwai  */
3758352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3759352f7f91STakashi Iwai 				   struct hda_codec *codec,
3760352f7f91STakashi Iwai 				   unsigned int stream_tag,
3761352f7f91STakashi Iwai 				   unsigned int format,
3762352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
3763352f7f91STakashi Iwai {
3764352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3765352f7f91STakashi Iwai 
3766352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
376797ec558aSTakashi Iwai 				   stream_tag, 0, format);
376897ec558aSTakashi Iwai 	return 0;
376997ec558aSTakashi Iwai }
377097ec558aSTakashi Iwai 
3771352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
377297ec558aSTakashi Iwai 				   struct hda_codec *codec,
377397ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
377497ec558aSTakashi Iwai {
3775352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
377697ec558aSTakashi Iwai 
3777352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
3778352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
377997ec558aSTakashi Iwai 	return 0;
378097ec558aSTakashi Iwai }
378197ec558aSTakashi Iwai 
3782352f7f91STakashi Iwai /*
3783352f7f91STakashi Iwai  */
3784352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
3785352f7f91STakashi Iwai 	.substreams = 1,
3786352f7f91STakashi Iwai 	.channels_min = 2,
3787352f7f91STakashi Iwai 	.channels_max = 8,
3788352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3789352f7f91STakashi Iwai 	.ops = {
3790352f7f91STakashi Iwai 		.open = playback_pcm_open,
379138cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
3792352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
3793352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
3794352f7f91STakashi Iwai 	},
3795352f7f91STakashi Iwai };
3796352f7f91STakashi Iwai 
3797352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
3798352f7f91STakashi Iwai 	.substreams = 1,
3799352f7f91STakashi Iwai 	.channels_min = 2,
3800352f7f91STakashi Iwai 	.channels_max = 2,
3801352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3802352f7f91STakashi Iwai };
3803352f7f91STakashi Iwai 
3804352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
3805352f7f91STakashi Iwai 	.substreams = 1,
3806352f7f91STakashi Iwai 	.channels_min = 2,
3807352f7f91STakashi Iwai 	.channels_max = 2,
3808352f7f91STakashi Iwai 	/* NID is set in build_pcms */
380938cf6f1aSTakashi Iwai 	.ops = {
381038cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
3811e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
3812e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
3813e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
381438cf6f1aSTakashi Iwai 	},
3815352f7f91STakashi Iwai };
3816352f7f91STakashi Iwai 
3817352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
3818352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
3819352f7f91STakashi Iwai 	.channels_min = 2,
3820352f7f91STakashi Iwai 	.channels_max = 2,
3821352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3822352f7f91STakashi Iwai 	.ops = {
3823352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
3824352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
3825352f7f91STakashi Iwai 	},
3826352f7f91STakashi Iwai };
3827352f7f91STakashi Iwai 
3828352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
3829352f7f91STakashi Iwai 	.substreams = 1,
3830352f7f91STakashi Iwai 	.channels_min = 2,
3831352f7f91STakashi Iwai 	.channels_max = 2,
3832352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3833352f7f91STakashi Iwai 	.ops = {
3834352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
3835352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
3836352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
3837352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
3838352f7f91STakashi Iwai 	},
3839352f7f91STakashi Iwai };
3840352f7f91STakashi Iwai 
3841352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
3842352f7f91STakashi Iwai 	.substreams = 1,
3843352f7f91STakashi Iwai 	.channels_min = 2,
3844352f7f91STakashi Iwai 	.channels_max = 2,
3845352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3846352f7f91STakashi Iwai };
3847352f7f91STakashi Iwai 
3848352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
3849352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
3850352f7f91STakashi Iwai 	.substreams = 0,
3851352f7f91STakashi Iwai 	.channels_min = 0,
3852352f7f91STakashi Iwai 	.channels_max = 0,
3853352f7f91STakashi Iwai };
3854352f7f91STakashi Iwai 
3855352f7f91STakashi Iwai /*
3856352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
3857352f7f91STakashi Iwai  */
3858352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
38591da177e4SLinus Torvalds {
3860352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3861352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
38621da177e4SLinus Torvalds 
3863352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
3864352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
3865352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3866352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
3867352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
3868352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
3869352f7f91STakashi Iwai 					   spec->cur_adc_format);
3870352f7f91STakashi Iwai 		return true;
3871352f7f91STakashi Iwai 	}
3872352f7f91STakashi Iwai 	return false;
3873352f7f91STakashi Iwai }
3874352f7f91STakashi Iwai 
3875352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
3876352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3877352f7f91STakashi Iwai 				       struct hda_codec *codec,
3878352f7f91STakashi Iwai 				       unsigned int stream_tag,
3879352f7f91STakashi Iwai 				       unsigned int format,
3880352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3881352f7f91STakashi Iwai {
3882352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3883352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
3884352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
3885352f7f91STakashi Iwai 	spec->cur_adc_format = format;
3886352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
38871da177e4SLinus Torvalds 	return 0;
38881da177e4SLinus Torvalds }
38891da177e4SLinus Torvalds 
3890352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3891352f7f91STakashi Iwai 				       struct hda_codec *codec,
3892352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3893352f7f91STakashi Iwai {
3894352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3895352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3896352f7f91STakashi Iwai 	spec->cur_adc = 0;
3897352f7f91STakashi Iwai 	return 0;
3898352f7f91STakashi Iwai }
3899352f7f91STakashi Iwai 
3900352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
3901352f7f91STakashi Iwai 	.substreams = 1,
3902352f7f91STakashi Iwai 	.channels_min = 2,
3903352f7f91STakashi Iwai 	.channels_max = 2,
3904352f7f91STakashi Iwai 	.nid = 0, /* fill later */
3905352f7f91STakashi Iwai 	.ops = {
3906352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
3907352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
3908352f7f91STakashi Iwai 	},
3909352f7f91STakashi Iwai };
3910352f7f91STakashi Iwai 
3911f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
3912f873e536STakashi Iwai 				 const char *chip_name)
3913f873e536STakashi Iwai {
3914f873e536STakashi Iwai 	char *p;
3915f873e536STakashi Iwai 
3916f873e536STakashi Iwai 	if (*str)
3917f873e536STakashi Iwai 		return;
3918f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
3919f873e536STakashi Iwai 
3920f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
3921f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
3922f873e536STakashi Iwai 		if (!isalnum(p[1])) {
3923f873e536STakashi Iwai 			*p = 0;
3924f873e536STakashi Iwai 			break;
3925f873e536STakashi Iwai 		}
3926f873e536STakashi Iwai 	}
3927f873e536STakashi Iwai 	strlcat(str, sfx, len);
3928f873e536STakashi Iwai }
3929f873e536STakashi Iwai 
3930352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
3931352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
3932352f7f91STakashi Iwai {
3933352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3934352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
3935352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
3936352f7f91STakashi Iwai 	bool have_multi_adcs;
3937352f7f91STakashi Iwai 
39381da177e4SLinus Torvalds 	codec->num_pcms = 1;
39391da177e4SLinus Torvalds 	codec->pcm_info = info;
39401da177e4SLinus Torvalds 
3941352f7f91STakashi Iwai 	if (spec->no_analog)
3942352f7f91STakashi Iwai 		goto skip_analog;
3943352f7f91STakashi Iwai 
3944f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
3945f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
3946f873e536STakashi Iwai 			     " Analog", codec->chip_name);
3947352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
3948352f7f91STakashi Iwai 
3949352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
3950352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
3951352f7f91STakashi Iwai 		if (!p)
3952352f7f91STakashi Iwai 			p = &pcm_analog_playback;
3953352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3954352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3955352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3956352f7f91STakashi Iwai 			spec->multiout.max_channels;
3957352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
3958352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
3959352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
3960352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
3961352f7f91STakashi Iwai 	}
3962352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
3963352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
3964352f7f91STakashi Iwai 		if (!p) {
3965352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
3966352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
3967352f7f91STakashi Iwai 			else
3968352f7f91STakashi Iwai 				p = &pcm_analog_capture;
3969352f7f91STakashi Iwai 		}
3970352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3971352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3972352f7f91STakashi Iwai 	}
3973352f7f91STakashi Iwai 
3974352f7f91STakashi Iwai  skip_analog:
3975352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
3976352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3977f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
3978352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
3979f873e536STakashi Iwai 				     " Digital", codec->chip_name);
3980352f7f91STakashi Iwai 		codec->num_pcms = 2;
3981352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
3982352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
3983352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
3984352f7f91STakashi Iwai 		if (spec->dig_out_type)
3985352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
3986352f7f91STakashi Iwai 		else
3987352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
3988352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
3989352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
3990352f7f91STakashi Iwai 			if (!p)
3991352f7f91STakashi Iwai 				p = &pcm_digital_playback;
3992352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3993352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3994352f7f91STakashi Iwai 		}
3995352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
3996352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
3997352f7f91STakashi Iwai 			if (!p)
3998352f7f91STakashi Iwai 				p = &pcm_digital_capture;
3999352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4000352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4001352f7f91STakashi Iwai 		}
4002352f7f91STakashi Iwai 	}
4003352f7f91STakashi Iwai 
4004352f7f91STakashi Iwai 	if (spec->no_analog)
4005352f7f91STakashi Iwai 		return 0;
4006352f7f91STakashi Iwai 
4007352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
4008352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
4009352f7f91STakashi Iwai 	 */
4010352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
4011352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
4012352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
4013352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
4014352f7f91STakashi Iwai 		codec->num_pcms = 3;
4015352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
4016352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
4017352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
4018352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
4019352f7f91STakashi Iwai 			if (!p)
4020352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
4021352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4022352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4023352f7f91STakashi Iwai 				spec->alt_dac_nid;
4024352f7f91STakashi Iwai 		} else {
4025352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4026352f7f91STakashi Iwai 				pcm_null_stream;
4027352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4028352f7f91STakashi Iwai 		}
4029352f7f91STakashi Iwai 		if (have_multi_adcs) {
4030352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
4031352f7f91STakashi Iwai 			if (!p)
4032352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
4033352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4034352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4035352f7f91STakashi Iwai 				spec->adc_nids[1];
4036352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4037352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
4038352f7f91STakashi Iwai 		} else {
4039352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4040352f7f91STakashi Iwai 				pcm_null_stream;
4041352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4042352f7f91STakashi Iwai 		}
40431da177e4SLinus Torvalds 	}
40441da177e4SLinus Torvalds 
40451da177e4SLinus Torvalds 	return 0;
40461da177e4SLinus Torvalds }
4047352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
4048352f7f91STakashi Iwai 
4049352f7f91STakashi Iwai 
4050352f7f91STakashi Iwai /*
4051352f7f91STakashi Iwai  * Standard auto-parser initializations
4052352f7f91STakashi Iwai  */
4053352f7f91STakashi Iwai 
4054d4156930STakashi Iwai /* configure the given path as a proper output */
40552c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
4056352f7f91STakashi Iwai {
4057352f7f91STakashi Iwai 	struct nid_path *path;
4058d4156930STakashi Iwai 	hda_nid_t pin;
4059352f7f91STakashi Iwai 
4060196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
4061d4156930STakashi Iwai 	if (!path || !path->depth)
4062352f7f91STakashi Iwai 		return;
4063d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
40642c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
4065e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
4066e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
4067352f7f91STakashi Iwai }
4068352f7f91STakashi Iwai 
4069352f7f91STakashi Iwai /* initialize primary output paths */
4070352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
4071352f7f91STakashi Iwai {
4072352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4073352f7f91STakashi Iwai 	int i;
4074352f7f91STakashi Iwai 
4075d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
40762c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
4077352f7f91STakashi Iwai }
4078352f7f91STakashi Iwai 
4079db23fd19STakashi Iwai 
40802c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
4081352f7f91STakashi Iwai {
4082352f7f91STakashi Iwai 	int i;
4083352f7f91STakashi Iwai 
4084d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
40852c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
4086352f7f91STakashi Iwai }
4087db23fd19STakashi Iwai 
4088db23fd19STakashi Iwai /* initialize hp and speaker paths */
4089db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
4090db23fd19STakashi Iwai {
4091db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4092db23fd19STakashi Iwai 
4093db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
40942c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
4095db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
4096db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
40972c12c30dSTakashi Iwai 				 spec->speaker_paths);
4098352f7f91STakashi Iwai }
4099352f7f91STakashi Iwai 
4100352f7f91STakashi Iwai /* initialize multi-io paths */
4101352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
4102352f7f91STakashi Iwai {
4103352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4104352f7f91STakashi Iwai 	int i;
4105352f7f91STakashi Iwai 
4106352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
4107352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
4108352f7f91STakashi Iwai 		struct nid_path *path;
4109196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
4110352f7f91STakashi Iwai 		if (!path)
4111352f7f91STakashi Iwai 			continue;
4112352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
4113352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
41142c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
4115352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
4116352f7f91STakashi Iwai 	}
4117352f7f91STakashi Iwai }
4118352f7f91STakashi Iwai 
4119352f7f91STakashi Iwai /* set up input pins and loopback paths */
4120352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
4121352f7f91STakashi Iwai {
4122352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4123352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4124352f7f91STakashi Iwai 	int i;
4125352f7f91STakashi Iwai 
4126352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4127352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4128352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
41292c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
4130352f7f91STakashi Iwai 
4131352f7f91STakashi Iwai 		/* init loopback inputs */
4132352f7f91STakashi Iwai 		if (spec->mixer_nid) {
4133352f7f91STakashi Iwai 			struct nid_path *path;
4134196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
4135352f7f91STakashi Iwai 			if (path)
4136352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
4137352f7f91STakashi Iwai 						      path->active, false);
4138352f7f91STakashi Iwai 		}
4139352f7f91STakashi Iwai 	}
4140352f7f91STakashi Iwai }
4141352f7f91STakashi Iwai 
4142352f7f91STakashi Iwai /* initialize ADC paths */
4143352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
4144352f7f91STakashi Iwai {
4145352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4146352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
4147352f7f91STakashi Iwai 	struct nid_path *path;
4148352f7f91STakashi Iwai 	int i, c, nums;
4149352f7f91STakashi Iwai 
4150352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4151352f7f91STakashi Iwai 		nums = 1;
4152352f7f91STakashi Iwai 	else
4153352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
4154352f7f91STakashi Iwai 
4155352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
4156352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
4157c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
4158352f7f91STakashi Iwai 			if (path) {
4159352f7f91STakashi Iwai 				bool active = path->active;
4160352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
4161352f7f91STakashi Iwai 					active = true;
4162352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
4163352f7f91STakashi Iwai 			}
4164352f7f91STakashi Iwai 		}
4165352f7f91STakashi Iwai 	}
4166352f7f91STakashi Iwai 
4167352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
4168352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
4169352f7f91STakashi Iwai 
4170352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
4171352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
4172352f7f91STakashi Iwai }
4173352f7f91STakashi Iwai 
4174352f7f91STakashi Iwai /* set right pin controls for digital I/O */
4175352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
4176352f7f91STakashi Iwai {
4177352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4178352f7f91STakashi Iwai 	int i;
4179352f7f91STakashi Iwai 	hda_nid_t pin;
4180352f7f91STakashi Iwai 
4181d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
41822c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
4183352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
41842430d7b7STakashi Iwai 	if (pin) {
41852430d7b7STakashi Iwai 		struct nid_path *path;
41862c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
41872430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
41882430d7b7STakashi Iwai 		if (path)
41892430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
41902430d7b7STakashi Iwai 	}
4191352f7f91STakashi Iwai }
4192352f7f91STakashi Iwai 
4193973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
4194973e4972STakashi Iwai  * invalid unsol tags by some reason
4195973e4972STakashi Iwai  */
4196973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
4197973e4972STakashi Iwai {
4198973e4972STakashi Iwai 	int i;
4199973e4972STakashi Iwai 
4200973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
4201973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
4202973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
4203973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
4204973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
4205973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
4206973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
4207973e4972STakashi Iwai 	}
4208973e4972STakashi Iwai }
4209973e4972STakashi Iwai 
42105187ac16STakashi Iwai /*
42115187ac16STakashi Iwai  * initialize the generic spec;
42125187ac16STakashi Iwai  * this can be put as patch_ops.init function
42135187ac16STakashi Iwai  */
4214352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
4215352f7f91STakashi Iwai {
4216352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4217352f7f91STakashi Iwai 
4218352f7f91STakashi Iwai 	if (spec->init_hook)
4219352f7f91STakashi Iwai 		spec->init_hook(codec);
4220352f7f91STakashi Iwai 
4221352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
4222352f7f91STakashi Iwai 
42233bbcd274STakashi Iwai 	codec->cached_write = 1;
42243bbcd274STakashi Iwai 
4225352f7f91STakashi Iwai 	init_multi_out(codec);
4226352f7f91STakashi Iwai 	init_extra_out(codec);
4227352f7f91STakashi Iwai 	init_multi_io(codec);
4228352f7f91STakashi Iwai 	init_analog_input(codec);
4229352f7f91STakashi Iwai 	init_input_src(codec);
4230352f7f91STakashi Iwai 	init_digital(codec);
4231352f7f91STakashi Iwai 
4232973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
4233973e4972STakashi Iwai 
4234352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
42355d550e15STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
42365d550e15STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
42375d550e15STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
4238352f7f91STakashi Iwai 
42393bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
42403bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
42413bbcd274STakashi Iwai 
4242352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
4243352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4244352f7f91STakashi Iwai 
4245352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
4246352f7f91STakashi Iwai 	return 0;
4247352f7f91STakashi Iwai }
4248fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
4249fce52a3bSTakashi Iwai 
42505187ac16STakashi Iwai /*
42515187ac16STakashi Iwai  * free the generic spec;
42525187ac16STakashi Iwai  * this can be put as patch_ops.free function
42535187ac16STakashi Iwai  */
4254fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
4255fce52a3bSTakashi Iwai {
4256fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
4257fce52a3bSTakashi Iwai 	kfree(codec->spec);
4258fce52a3bSTakashi Iwai 	codec->spec = NULL;
4259fce52a3bSTakashi Iwai }
4260fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
4261fce52a3bSTakashi Iwai 
4262fce52a3bSTakashi Iwai #ifdef CONFIG_PM
42635187ac16STakashi Iwai /*
42645187ac16STakashi Iwai  * check the loopback power save state;
42655187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
42665187ac16STakashi Iwai  */
4267fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4268fce52a3bSTakashi Iwai {
4269fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4270fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4271fce52a3bSTakashi Iwai }
4272fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
4273fce52a3bSTakashi Iwai #endif
4274352f7f91STakashi Iwai 
4275352f7f91STakashi Iwai 
4276352f7f91STakashi Iwai /*
4277352f7f91STakashi Iwai  * the generic codec support
4278352f7f91STakashi Iwai  */
42791da177e4SLinus Torvalds 
4280352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
4281352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
4282352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
4283352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
4284fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
4285352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
428683012a7cSTakashi Iwai #ifdef CONFIG_PM
4287fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
4288cb53c626STakashi Iwai #endif
42891da177e4SLinus Torvalds };
42901da177e4SLinus Torvalds 
42911da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
42921da177e4SLinus Torvalds {
4293352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
42941da177e4SLinus Torvalds 	int err;
42951da177e4SLinus Torvalds 
4296e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4297352f7f91STakashi Iwai 	if (!spec)
42981da177e4SLinus Torvalds 		return -ENOMEM;
4299352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
43001da177e4SLinus Torvalds 	codec->spec = spec;
43011da177e4SLinus Torvalds 
43029eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
43039eb413e5STakashi Iwai 	if (err < 0)
43049eb413e5STakashi Iwai 		return err;
43059eb413e5STakashi Iwai 
43069eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
4307352f7f91STakashi Iwai 	if (err < 0)
43081da177e4SLinus Torvalds 		goto error;
43091da177e4SLinus Torvalds 
43101da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
43111da177e4SLinus Torvalds 	return 0;
43121da177e4SLinus Torvalds 
43131da177e4SLinus Torvalds error:
4314fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
43151da177e4SLinus Torvalds 	return err;
43161da177e4SLinus Torvalds }
4317fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
4318