xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 708122e8)
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->bind_ctls, sizeof(struct hda_bind_ctls *), 8);
43352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
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 static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
78352f7f91STakashi Iwai 					  unsigned int nums,
79352f7f91STakashi Iwai 					  struct hda_ctl_ops *ops)
80352f7f91STakashi Iwai {
81352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
82352f7f91STakashi Iwai 	struct hda_bind_ctls **ctlp, *ctl;
83352f7f91STakashi Iwai 	ctlp = snd_array_new(&spec->bind_ctls);
84352f7f91STakashi Iwai 	if (!ctlp)
85352f7f91STakashi Iwai 		return NULL;
86352f7f91STakashi Iwai 	ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
87352f7f91STakashi Iwai 	*ctlp = ctl;
88352f7f91STakashi Iwai 	if (ctl)
89352f7f91STakashi Iwai 		ctl->ops = ops;
90352f7f91STakashi Iwai 	return ctl;
91352f7f91STakashi Iwai }
92352f7f91STakashi Iwai 
93352f7f91STakashi Iwai static void free_bind_ctls(struct hda_gen_spec *spec)
94352f7f91STakashi Iwai {
95352f7f91STakashi Iwai 	if (spec->bind_ctls.list) {
96352f7f91STakashi Iwai 		struct hda_bind_ctls **ctl = spec->bind_ctls.list;
97352f7f91STakashi Iwai 		int i;
98352f7f91STakashi Iwai 		for (i = 0; i < spec->bind_ctls.used; i++)
99352f7f91STakashi Iwai 			kfree(ctl[i]);
100352f7f91STakashi Iwai 	}
101352f7f91STakashi Iwai 	snd_array_free(&spec->bind_ctls);
102352f7f91STakashi Iwai }
103352f7f91STakashi Iwai 
104352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
105352f7f91STakashi Iwai {
1061da177e4SLinus Torvalds 	if (!spec)
1071da177e4SLinus Torvalds 		return;
108352f7f91STakashi Iwai 	free_kctls(spec);
109352f7f91STakashi Iwai 	free_bind_ctls(spec);
110352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1111da177e4SLinus Torvalds }
112352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds /*
115352f7f91STakashi Iwai  * parsing paths
1161da177e4SLinus Torvalds  */
1171da177e4SLinus Torvalds 
118352f7f91STakashi Iwai /* get the path between the given NIDs;
119352f7f91STakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
1201da177e4SLinus Torvalds  */
121352f7f91STakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
122352f7f91STakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
1231da177e4SLinus Torvalds {
124352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
125352f7f91STakashi Iwai 	int i;
1261da177e4SLinus Torvalds 
127352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
128352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
129352f7f91STakashi Iwai 		if (path->depth <= 0)
130352f7f91STakashi Iwai 			continue;
131352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
132352f7f91STakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid))
133352f7f91STakashi Iwai 			return path;
1341da177e4SLinus Torvalds 	}
1351da177e4SLinus Torvalds 	return NULL;
1361da177e4SLinus Torvalds }
137352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
1381da177e4SLinus Torvalds 
139352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
140352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
1411da177e4SLinus Torvalds {
142352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
143352f7f91STakashi Iwai 	int i;
144352f7f91STakashi Iwai 
145352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
146352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
147352f7f91STakashi Iwai 		if (path->path[0] == nid)
148352f7f91STakashi Iwai 			return true;
149352f7f91STakashi Iwai 	}
150352f7f91STakashi Iwai 	return false;
1511da177e4SLinus Torvalds }
1521da177e4SLinus Torvalds 
153352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
154352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
155352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
1561da177e4SLinus Torvalds {
157352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
158352f7f91STakashi Iwai 		return false;
159352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
1601da177e4SLinus Torvalds }
1611da177e4SLinus Torvalds 
162352f7f91STakashi Iwai /* nid, dir and idx */
163352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
164352f7f91STakashi Iwai 
165352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
166352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
1671da177e4SLinus Torvalds {
168352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
169352f7f91STakashi Iwai 	int i;
170352f7f91STakashi Iwai 
171352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
172352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
173352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
174352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
175352f7f91STakashi Iwai 			return true;
176352f7f91STakashi Iwai 	}
177352f7f91STakashi Iwai 	return false;
1781da177e4SLinus Torvalds }
1791da177e4SLinus Torvalds 
180352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
181352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
182cb53c626STakashi Iwai 			      int dir, int idx)
183cb53c626STakashi Iwai {
184352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
185352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
186352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
187cb53c626STakashi Iwai }
188352f7f91STakashi Iwai 
1890c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
1900c8c0f56STakashi Iwai {
1910c8c0f56STakashi Iwai 	char buf[40];
1920c8c0f56STakashi Iwai 	int i;
1930c8c0f56STakashi Iwai 
1940c8c0f56STakashi Iwai 
1950c8c0f56STakashi Iwai 	buf[0] = 0;
1960c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
1970c8c0f56STakashi Iwai 		char tmp[4];
1980c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
1990c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
2000c8c0f56STakashi Iwai 	}
2010c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
2020c8c0f56STakashi Iwai }
2030c8c0f56STakashi Iwai 
204352f7f91STakashi Iwai /* called recursively */
205352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
206352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
207352f7f91STakashi Iwai 			     int with_aa_mix, struct nid_path *path, int depth)
208352f7f91STakashi Iwai {
209352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
210352f7f91STakashi Iwai 	hda_nid_t conn[16];
211352f7f91STakashi Iwai 	int i, nums;
212352f7f91STakashi Iwai 
213352f7f91STakashi Iwai 	if (to_nid == spec->mixer_nid) {
214352f7f91STakashi Iwai 		if (!with_aa_mix)
215352f7f91STakashi Iwai 			return false;
216352f7f91STakashi Iwai 		with_aa_mix = 2; /* mark aa-mix is included */
217352f7f91STakashi Iwai 	}
218352f7f91STakashi Iwai 
219352f7f91STakashi Iwai 	nums = snd_hda_get_connections(codec, to_nid, conn, ARRAY_SIZE(conn));
220352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
221352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
222352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
223352f7f91STakashi Iwai 			 * try to find an empty DAC
224352f7f91STakashi Iwai 			 */
225352f7f91STakashi Iwai 			if (from_nid ||
226352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
227352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
228352f7f91STakashi Iwai 				continue;
229352f7f91STakashi Iwai 		}
230352f7f91STakashi Iwai 		/* aa-mix is requested but not included? */
231352f7f91STakashi Iwai 		if (!(spec->mixer_nid && with_aa_mix == 1))
232352f7f91STakashi Iwai 			goto found;
233352f7f91STakashi Iwai 	}
234352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
235352f7f91STakashi Iwai 		return false;
236352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
237352f7f91STakashi Iwai 		unsigned int type;
238352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
239352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
240352f7f91STakashi Iwai 		    type == AC_WID_PIN)
241352f7f91STakashi Iwai 			continue;
242352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
243352f7f91STakashi Iwai 				     with_aa_mix, path, depth + 1))
244352f7f91STakashi Iwai 			goto found;
245352f7f91STakashi Iwai 	}
246352f7f91STakashi Iwai 	return false;
247352f7f91STakashi Iwai 
248352f7f91STakashi Iwai  found:
249352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
250352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
251352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
252352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
253352f7f91STakashi Iwai 	path->depth++;
254352f7f91STakashi Iwai 	return true;
255352f7f91STakashi Iwai }
256352f7f91STakashi Iwai 
257352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
258352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
259352f7f91STakashi Iwai  * when @with_aa_mix is 0, paths with spec->mixer_nid are excluded.
260352f7f91STakashi Iwai  * when @with_aa_mix is 1, paths without spec->mixer_nid are excluded.
261352f7f91STakashi Iwai  * when @with_aa_mix is 2, no special handling about spec->mixer_nid.
262352f7f91STakashi Iwai  */
263352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
264352f7f91STakashi Iwai 			    hda_nid_t to_nid, int with_aa_mix,
265352f7f91STakashi Iwai 			    struct nid_path *path)
266352f7f91STakashi Iwai {
267352f7f91STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) {
268352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
269352f7f91STakashi Iwai 		path->depth++;
270352f7f91STakashi Iwai 		return true;
271352f7f91STakashi Iwai 	}
272352f7f91STakashi Iwai 	return false;
273352f7f91STakashi Iwai }
274352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
275352f7f91STakashi Iwai 
276352f7f91STakashi Iwai /*
277352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
278352f7f91STakashi Iwai  * if no valid path is found, return NULL
279352f7f91STakashi Iwai  */
280352f7f91STakashi Iwai struct nid_path *
281352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
282352f7f91STakashi Iwai 		     hda_nid_t to_nid, int with_aa_mix)
283352f7f91STakashi Iwai {
284352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
285352f7f91STakashi Iwai 	struct nid_path *path;
286352f7f91STakashi Iwai 
287352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
288352f7f91STakashi Iwai 		return NULL;
289352f7f91STakashi Iwai 
290352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
291352f7f91STakashi Iwai 	if (!path)
292352f7f91STakashi Iwai 		return NULL;
293352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
294352f7f91STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path))
295352f7f91STakashi Iwai 		return path;
296352f7f91STakashi Iwai 	/* push back */
297352f7f91STakashi Iwai 	spec->paths.used--;
298352f7f91STakashi Iwai 	return NULL;
299352f7f91STakashi Iwai }
300352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
301352f7f91STakashi Iwai 
302352f7f91STakashi Iwai /* look for an empty DAC slot */
303352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
304352f7f91STakashi Iwai 			      bool is_digital)
305352f7f91STakashi Iwai {
306352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
307352f7f91STakashi Iwai 	bool cap_digital;
308352f7f91STakashi Iwai 	int i;
309352f7f91STakashi Iwai 
310352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
311352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
312352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
313352f7f91STakashi Iwai 			continue;
314352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
315352f7f91STakashi Iwai 		if (is_digital != cap_digital)
316352f7f91STakashi Iwai 			continue;
317352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
318352f7f91STakashi Iwai 			return nid;
319352f7f91STakashi Iwai 	}
320352f7f91STakashi Iwai 	return 0;
321352f7f91STakashi Iwai }
322352f7f91STakashi Iwai 
323352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
324352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
325352f7f91STakashi Iwai {
326352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
327352f7f91STakashi Iwai 	val |= chs << 16;
328352f7f91STakashi Iwai 	return val;
329352f7f91STakashi Iwai }
330352f7f91STakashi Iwai 
331352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
332352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
333352f7f91STakashi Iwai 			   int dir, unsigned int bits)
334352f7f91STakashi Iwai {
335352f7f91STakashi Iwai 	if (!nid)
336352f7f91STakashi Iwai 		return false;
337352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
338352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
339352f7f91STakashi Iwai 			return true;
340352f7f91STakashi Iwai 	return false;
341352f7f91STakashi Iwai }
342352f7f91STakashi Iwai 
343352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
344352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
345352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
346352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
347352f7f91STakashi Iwai 
348352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
349352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
350352f7f91STakashi Iwai 				       struct nid_path *path)
351352f7f91STakashi Iwai {
352352f7f91STakashi Iwai 	int i;
353352f7f91STakashi Iwai 
354352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
355352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
356352f7f91STakashi Iwai 			return path->path[i];
357352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
358352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
359352f7f91STakashi Iwai 			return path->path[i];
360352f7f91STakashi Iwai 	}
361352f7f91STakashi Iwai 	return 0;
362352f7f91STakashi Iwai }
363352f7f91STakashi Iwai 
364352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
365352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
366352f7f91STakashi Iwai 				      struct nid_path *path)
367352f7f91STakashi Iwai {
368352f7f91STakashi Iwai 	int i;
369352f7f91STakashi Iwai 
370352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
371352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
372352f7f91STakashi Iwai 			return path->path[i];
373352f7f91STakashi Iwai 	}
374352f7f91STakashi Iwai 	return 0;
375352f7f91STakashi Iwai }
376352f7f91STakashi Iwai 
377352f7f91STakashi Iwai /*
378352f7f91STakashi Iwai  * path activation / deactivation
379352f7f91STakashi Iwai  */
380352f7f91STakashi Iwai 
381352f7f91STakashi Iwai /* can have the amp-in capability? */
382352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
383352f7f91STakashi Iwai {
384352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
385352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
386352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
387352f7f91STakashi Iwai 
388352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
389352f7f91STakashi Iwai 		return false;
390352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
391352f7f91STakashi Iwai 		return false;
392352f7f91STakashi Iwai 	return true;
393352f7f91STakashi Iwai }
394352f7f91STakashi Iwai 
395352f7f91STakashi Iwai /* can have the amp-out capability? */
396352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
397352f7f91STakashi Iwai {
398352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
399352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
400352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
401352f7f91STakashi Iwai 
402352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
403352f7f91STakashi Iwai 		return false;
404352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
405352f7f91STakashi Iwai 		return false;
406352f7f91STakashi Iwai 	return true;
407352f7f91STakashi Iwai }
408352f7f91STakashi Iwai 
409352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
410352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
411352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
412352f7f91STakashi Iwai {
413352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
414352f7f91STakashi Iwai 	int i, n;
415352f7f91STakashi Iwai 
416352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
417352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
418352f7f91STakashi Iwai 		if (!path->active)
419352f7f91STakashi Iwai 			continue;
420352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
421352f7f91STakashi Iwai 			if (path->path[i] == nid) {
422352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
423352f7f91STakashi Iwai 					return true;
424352f7f91STakashi Iwai 				break;
425352f7f91STakashi Iwai 			}
426352f7f91STakashi Iwai 		}
427352f7f91STakashi Iwai 	}
428352f7f91STakashi Iwai 	return false;
429352f7f91STakashi Iwai }
430352f7f91STakashi Iwai 
431352f7f91STakashi Iwai /* get the default amp value for the target state */
432352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
433352f7f91STakashi Iwai 				   int dir, bool enable)
434352f7f91STakashi Iwai {
435352f7f91STakashi Iwai 	unsigned int caps;
436352f7f91STakashi Iwai 	unsigned int val = 0;
437352f7f91STakashi Iwai 
438352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
439352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
440352f7f91STakashi Iwai 		/* set to 0dB */
441352f7f91STakashi Iwai 		if (enable)
442352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
443352f7f91STakashi Iwai 	}
444352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
445352f7f91STakashi Iwai 		if (!enable)
446352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
447352f7f91STakashi Iwai 	}
448352f7f91STakashi Iwai 	return val;
449352f7f91STakashi Iwai }
450352f7f91STakashi Iwai 
451352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
452352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
453352f7f91STakashi Iwai {
454352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
455352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
456352f7f91STakashi Iwai }
457352f7f91STakashi Iwai 
458352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
459352f7f91STakashi Iwai 			 int idx, bool enable)
460352f7f91STakashi Iwai {
461352f7f91STakashi Iwai 	int val;
462352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
463352f7f91STakashi Iwai 	    is_active_nid(codec, nid, dir, idx))
464352f7f91STakashi Iwai 		return;
465352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
466352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
467352f7f91STakashi Iwai }
468352f7f91STakashi Iwai 
469352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
470352f7f91STakashi Iwai 			     int i, bool enable)
471352f7f91STakashi Iwai {
472352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
473352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
474352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
475352f7f91STakashi Iwai }
476352f7f91STakashi Iwai 
477352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
478352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
479352f7f91STakashi Iwai {
480352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
481352f7f91STakashi Iwai 	hda_nid_t conn[16];
482352f7f91STakashi Iwai 	int n, nums, idx;
483352f7f91STakashi Iwai 	int type;
484352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
485352f7f91STakashi Iwai 
486352f7f91STakashi Iwai 	nums = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn));
487352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
488352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
489352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
490352f7f91STakashi Iwai 		nums = 1;
491352f7f91STakashi Iwai 		idx = 0;
492352f7f91STakashi Iwai 	} else
493352f7f91STakashi Iwai 		idx = path->idx[i];
494352f7f91STakashi Iwai 
495352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
496352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
497352f7f91STakashi Iwai 
498352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
499352f7f91STakashi Iwai 		return;
500352f7f91STakashi Iwai 
501352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
502352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
503352f7f91STakashi Iwai 	 */
504352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
505352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
506352f7f91STakashi Iwai 			continue;
507352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
508352f7f91STakashi Iwai 	}
509352f7f91STakashi Iwai }
510352f7f91STakashi Iwai 
511352f7f91STakashi Iwai /* activate or deactivate the given path
512352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
513352f7f91STakashi Iwai  */
514352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
515352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
516352f7f91STakashi Iwai {
517352f7f91STakashi Iwai 	int i;
518352f7f91STakashi Iwai 
519352f7f91STakashi Iwai 	if (!enable)
520352f7f91STakashi Iwai 		path->active = false;
521352f7f91STakashi Iwai 
522352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
523352f7f91STakashi Iwai 		if (enable && path->multi[i])
524352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
525352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
526352f7f91STakashi Iwai 					    path->idx[i]);
527352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
528352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
529352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
530352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
531352f7f91STakashi Iwai 	}
532352f7f91STakashi Iwai 
533352f7f91STakashi Iwai 	if (enable)
534352f7f91STakashi Iwai 		path->active = true;
535352f7f91STakashi Iwai }
536352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
537352f7f91STakashi Iwai 
538d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
539d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
540d5a9f1bbSTakashi Iwai {
541d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
542d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
543d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
544d5a9f1bbSTakashi Iwai 		return;
545d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
546d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
547d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
548d5a9f1bbSTakashi Iwai }
549d5a9f1bbSTakashi Iwai 
550352f7f91STakashi Iwai 
551352f7f91STakashi Iwai /*
552352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
553352f7f91STakashi Iwai  */
554352f7f91STakashi Iwai 
555352f7f91STakashi Iwai enum {
556352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
557352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
558352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
559352f7f91STakashi Iwai 	HDA_CTL_BIND_VOL,
560352f7f91STakashi Iwai 	HDA_CTL_BIND_SW,
561352f7f91STakashi Iwai };
562352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
563352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
564352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
565352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
566352f7f91STakashi Iwai 	HDA_BIND_VOL(NULL, 0),
567352f7f91STakashi Iwai 	HDA_BIND_SW(NULL, 0),
568352f7f91STakashi Iwai };
569352f7f91STakashi Iwai 
570352f7f91STakashi Iwai /* add dynamic controls from template */
571352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
572352f7f91STakashi Iwai 		       int cidx, unsigned long val)
573352f7f91STakashi Iwai {
574352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
575352f7f91STakashi Iwai 
57612c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
577352f7f91STakashi Iwai 	if (!knew)
578352f7f91STakashi Iwai 		return -ENOMEM;
579352f7f91STakashi Iwai 	knew->index = cidx;
580352f7f91STakashi Iwai 	if (get_amp_nid_(val))
581352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
582352f7f91STakashi Iwai 	knew->private_value = val;
583352f7f91STakashi Iwai 	return 0;
584352f7f91STakashi Iwai }
585352f7f91STakashi Iwai 
586352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
587352f7f91STakashi Iwai 				const char *pfx, const char *dir,
588352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
589352f7f91STakashi Iwai {
590352f7f91STakashi Iwai 	char name[32];
591352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
592352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
593352f7f91STakashi Iwai }
594352f7f91STakashi Iwai 
595352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
596352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
597352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
598352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
599352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
600352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
601352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
602352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
605352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
606352f7f91STakashi Iwai {
607352f7f91STakashi Iwai 	unsigned int val;
608352f7f91STakashi Iwai 	if (!path)
609352f7f91STakashi Iwai 		return 0;
610352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
611352f7f91STakashi Iwai 	if (!val)
612352f7f91STakashi Iwai 		return 0;
613352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
614352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
615352f7f91STakashi Iwai }
616352f7f91STakashi Iwai 
617352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
618352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
619352f7f91STakashi Iwai 			       int type)
620352f7f91STakashi Iwai {
621352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
622352f7f91STakashi Iwai 	if (path) {
623352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
624352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
625352f7f91STakashi Iwai 			chs = 3; /* stereo */
626352f7f91STakashi Iwai 	}
627352f7f91STakashi Iwai 	return chs;
628352f7f91STakashi Iwai }
629352f7f91STakashi Iwai 
630352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
631352f7f91STakashi Iwai 			  struct nid_path *path)
632352f7f91STakashi Iwai {
633352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
634352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
635352f7f91STakashi Iwai }
636352f7f91STakashi Iwai 
637352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
638352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
639352f7f91STakashi Iwai  */
640352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
641352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
642352f7f91STakashi Iwai {
643352f7f91STakashi Iwai 	unsigned int val;
644352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
645352f7f91STakashi Iwai 
646352f7f91STakashi Iwai 	if (!path)
647352f7f91STakashi Iwai 		return 0;
648352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
649352f7f91STakashi Iwai 	if (!val)
650352f7f91STakashi Iwai 		return 0;
651352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
652352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
653352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
654352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
655352f7f91STakashi Iwai 		if (nums > 1) {
656352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
657352f7f91STakashi Iwai 			val |= nums << 19;
658352f7f91STakashi Iwai 		}
659352f7f91STakashi Iwai 	}
660352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
661352f7f91STakashi Iwai }
662352f7f91STakashi Iwai 
663352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
664352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
665352f7f91STakashi Iwai {
666352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
667352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
668352f7f91STakashi Iwai }
669352f7f91STakashi Iwai 
670352f7f91STakashi Iwai static const char * const channel_name[4] = {
671352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
672352f7f91STakashi Iwai };
673352f7f91STakashi Iwai 
674352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
675352f7f91STakashi Iwai static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch,
676352f7f91STakashi Iwai 				    bool can_be_master, int *index)
677352f7f91STakashi Iwai {
678352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
679352f7f91STakashi Iwai 
680352f7f91STakashi Iwai 	*index = 0;
681352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
682352f7f91STakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
683352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
684352f7f91STakashi Iwai 
685352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
686352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
687352f7f91STakashi Iwai 	 */
688352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
689352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
690352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
691352f7f91STakashi Iwai 
692352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
693352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
694352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
695352f7f91STakashi Iwai 			return "Speaker";
696352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
697352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
698352f7f91STakashi Iwai 		break;
699352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
700352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
701352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
702352f7f91STakashi Iwai 			break;
703352f7f91STakashi Iwai 		*index = ch;
704352f7f91STakashi Iwai 		return "Headphone";
705352f7f91STakashi Iwai 	default:
706352f7f91STakashi Iwai 		if (cfg->line_outs == 1 && !spec->multi_ios)
707352f7f91STakashi Iwai 			return "PCM";
708352f7f91STakashi Iwai 		break;
709352f7f91STakashi Iwai 	}
710352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
711352f7f91STakashi Iwai 		snd_BUG();
712352f7f91STakashi Iwai 		return "PCM";
713352f7f91STakashi Iwai 	}
714352f7f91STakashi Iwai 
715352f7f91STakashi Iwai 	return channel_name[ch];
716352f7f91STakashi Iwai }
717352f7f91STakashi Iwai 
718352f7f91STakashi Iwai /*
719352f7f91STakashi Iwai  * Parse output paths
720352f7f91STakashi Iwai  */
721352f7f91STakashi Iwai 
722352f7f91STakashi Iwai /* badness definition */
723352f7f91STakashi Iwai enum {
724352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
725352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
726352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
727352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
728352f7f91STakashi Iwai 	/* No possible multi-ios */
729352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
730352f7f91STakashi Iwai 	/* No individual DAC for extra output */
731352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
732352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
733352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
734352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
735352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
736352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
737352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
738352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
739352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
740352f7f91STakashi Iwai 	/* Volume widget is shared */
741352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
742352f7f91STakashi Iwai };
743352f7f91STakashi Iwai 
744352f7f91STakashi Iwai /* look for widgets in the path between the given NIDs appropriate for
745352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
746352f7f91STakashi Iwai  *
747352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
748352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
749352f7f91STakashi Iwai  * total badness for both volume and mute controls.
750352f7f91STakashi Iwai  */
751352f7f91STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, hda_nid_t pin,
752352f7f91STakashi Iwai 				hda_nid_t dac)
753352f7f91STakashi Iwai {
754352f7f91STakashi Iwai 	struct nid_path *path = snd_hda_get_nid_path(codec, dac, pin);
755352f7f91STakashi Iwai 	hda_nid_t nid;
756352f7f91STakashi Iwai 	unsigned int val;
757352f7f91STakashi Iwai 	int badness = 0;
758352f7f91STakashi Iwai 
759352f7f91STakashi Iwai 	if (!path)
760352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
761352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
762352f7f91STakashi Iwai 	if (nid) {
763352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
764352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
765352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
766352f7f91STakashi Iwai 		else
767352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
768352f7f91STakashi Iwai 	} else
769352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
770352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
771352f7f91STakashi Iwai 	if (nid) {
772352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
773352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
774352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
775352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
776352f7f91STakashi Iwai 		else
777352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
778352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
779352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
780352f7f91STakashi Iwai 		else
781352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
782352f7f91STakashi Iwai 	} else
783352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
784352f7f91STakashi Iwai 	return badness;
785352f7f91STakashi Iwai }
786352f7f91STakashi Iwai 
787352f7f91STakashi Iwai struct badness_table {
788352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
789352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
790352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
791352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
792352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
793352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
794352f7f91STakashi Iwai };
795352f7f91STakashi Iwai 
796352f7f91STakashi Iwai static struct badness_table main_out_badness = {
797352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
798352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
799352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
800352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
801352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
802352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
803352f7f91STakashi Iwai };
804352f7f91STakashi Iwai 
805352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
806352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
807352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
808352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
809352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
810352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
811352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
812352f7f91STakashi Iwai };
813352f7f91STakashi Iwai 
814352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
815352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
816352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
817352f7f91STakashi Iwai 			   const struct badness_table *bad)
818352f7f91STakashi Iwai {
819352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
820352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
821352f7f91STakashi Iwai 	int i, j;
822352f7f91STakashi Iwai 	int badness = 0;
823352f7f91STakashi Iwai 	hda_nid_t dac;
824352f7f91STakashi Iwai 
825352f7f91STakashi Iwai 	if (!num_outs)
826352f7f91STakashi Iwai 		return 0;
827352f7f91STakashi Iwai 
828352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
8290c8c0f56STakashi Iwai 		struct nid_path *path;
830352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
831352f7f91STakashi Iwai 		if (!dacs[i])
832352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
833352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
834352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
835352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
836352f7f91STakashi Iwai 					dacs[0] = dacs[j];
837352f7f91STakashi Iwai 					dacs[j] = 0;
838352f7f91STakashi Iwai 					break;
839352f7f91STakashi Iwai 				}
840352f7f91STakashi Iwai 			}
841352f7f91STakashi Iwai 		}
842352f7f91STakashi Iwai 		dac = dacs[i];
843352f7f91STakashi Iwai 		if (!dac) {
844352f7f91STakashi Iwai 			if (is_reachable_path(codec, dacs[0], pin))
845352f7f91STakashi Iwai 				dac = dacs[0];
846352f7f91STakashi Iwai 			else if (cfg->line_outs > i &&
847352f7f91STakashi Iwai 				 is_reachable_path(codec, spec->private_dac_nids[i], pin))
848352f7f91STakashi Iwai 				dac = spec->private_dac_nids[i];
849352f7f91STakashi Iwai 			if (dac) {
850352f7f91STakashi Iwai 				if (!i)
851352f7f91STakashi Iwai 					badness += bad->shared_primary;
852352f7f91STakashi Iwai 				else if (i == 1)
853352f7f91STakashi Iwai 					badness += bad->shared_surr;
854352f7f91STakashi Iwai 				else
855352f7f91STakashi Iwai 					badness += bad->shared_clfe;
856352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
857352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
858352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
859352f7f91STakashi Iwai 			} else if (!i)
860352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
861352f7f91STakashi Iwai 			else
862352f7f91STakashi Iwai 				badness += bad->no_dac;
863352f7f91STakashi Iwai 		}
8640c8c0f56STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, 0);
8650c8c0f56STakashi Iwai 		if (!path)
866352f7f91STakashi Iwai 			dac = dacs[i] = 0;
8670c8c0f56STakashi Iwai 		else
8680c8c0f56STakashi Iwai 			print_nid_path("output", path);
869352f7f91STakashi Iwai 		if (dac)
870352f7f91STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dac);
871352f7f91STakashi Iwai 	}
872352f7f91STakashi Iwai 
873352f7f91STakashi Iwai 	return badness;
874352f7f91STakashi Iwai }
875352f7f91STakashi Iwai 
876352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
877352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
878352f7f91STakashi Iwai {
879352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
880352f7f91STakashi Iwai 	int i;
881352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
882352f7f91STakashi Iwai 
883352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
884352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
885352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
886352f7f91STakashi Iwai 			continue;
887352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
888352f7f91STakashi Iwai 			if (nid_found)
889352f7f91STakashi Iwai 				return 0;
890352f7f91STakashi Iwai 			nid_found = nid;
891352f7f91STakashi Iwai 		}
892352f7f91STakashi Iwai 	}
893352f7f91STakashi Iwai 	return nid_found;
894352f7f91STakashi Iwai }
895352f7f91STakashi Iwai 
896352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
897352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
898352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
899352f7f91STakashi Iwai {
900352f7f91STakashi Iwai 	unsigned int defcfg, caps;
901352f7f91STakashi Iwai 
902352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
903352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
904352f7f91STakashi Iwai 		return false;
905352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
906352f7f91STakashi Iwai 		return false;
907352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
908352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
909352f7f91STakashi Iwai 		return false;
910352f7f91STakashi Iwai 	return true;
911352f7f91STakashi Iwai }
912352f7f91STakashi Iwai 
913352f7f91STakashi Iwai /*
914352f7f91STakashi Iwai  * multi-io helper
915352f7f91STakashi Iwai  *
916352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
917352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
918352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
919352f7f91STakashi Iwai  * the badness value.
920352f7f91STakashi Iwai  */
921352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
922352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
923352f7f91STakashi Iwai 			  bool hardwired, int offset)
924352f7f91STakashi Iwai {
925352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
926352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
927352f7f91STakashi Iwai 	int type, i, j, dacs, num_pins, old_pins;
928352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
929352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
930352f7f91STakashi Iwai 	int badness = 0;
931352f7f91STakashi Iwai 
932352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
933352f7f91STakashi Iwai 	if (old_pins >= 2)
934352f7f91STakashi Iwai 		goto end_fill;
935352f7f91STakashi Iwai 
936352f7f91STakashi Iwai 	num_pins = 0;
937352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
938352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
939352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
940352f7f91STakashi Iwai 				continue;
941352f7f91STakashi Iwai 			if (can_be_multiio_pin(codec, location,
942352f7f91STakashi Iwai 					       cfg->inputs[i].pin))
943352f7f91STakashi Iwai 				num_pins++;
944352f7f91STakashi Iwai 		}
945352f7f91STakashi Iwai 	}
946352f7f91STakashi Iwai 	if (num_pins < 2)
947352f7f91STakashi Iwai 		goto end_fill;
948352f7f91STakashi Iwai 
949352f7f91STakashi Iwai 	dacs = spec->multiout.num_dacs;
950352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
951352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
9520c8c0f56STakashi Iwai 			struct nid_path *path;
953352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
954352f7f91STakashi Iwai 			hda_nid_t dac = 0;
955352f7f91STakashi Iwai 
956352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
957352f7f91STakashi Iwai 				continue;
958352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
959352f7f91STakashi Iwai 				continue;
960352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
961352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
962352f7f91STakashi Iwai 					break;
963352f7f91STakashi Iwai 			}
964352f7f91STakashi Iwai 			if (j < spec->multi_ios)
965352f7f91STakashi Iwai 				continue;
966352f7f91STakashi Iwai 
967352f7f91STakashi Iwai 			if (offset && offset + spec->multi_ios < dacs) {
968352f7f91STakashi Iwai 				dac = spec->private_dac_nids[offset + spec->multi_ios];
969352f7f91STakashi Iwai 				if (!is_reachable_path(codec, dac, nid))
970352f7f91STakashi Iwai 					dac = 0;
971352f7f91STakashi Iwai 			}
972352f7f91STakashi Iwai 			if (hardwired)
973352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
974352f7f91STakashi Iwai 			else if (!dac)
975352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
976352f7f91STakashi Iwai 			if (!dac) {
977352f7f91STakashi Iwai 				badness++;
978352f7f91STakashi Iwai 				continue;
979352f7f91STakashi Iwai 			}
9800c8c0f56STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid, 0);
9810c8c0f56STakashi Iwai 			if (!path) {
982352f7f91STakashi Iwai 				badness++;
983352f7f91STakashi Iwai 				continue;
984352f7f91STakashi Iwai 			}
9850c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
986352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
987352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
988352f7f91STakashi Iwai 			spec->multi_ios++;
989352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
990352f7f91STakashi Iwai 				break;
991352f7f91STakashi Iwai 		}
992352f7f91STakashi Iwai 	}
993352f7f91STakashi Iwai  end_fill:
994352f7f91STakashi Iwai 	if (badness)
995352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
996352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
997352f7f91STakashi Iwai 		if (hardwired)
998352f7f91STakashi Iwai 			return 1; /* nothing found */
999352f7f91STakashi Iwai 		else
1000352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1001352f7f91STakashi Iwai 	}
1002352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1003352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1004352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1005352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1006352f7f91STakashi Iwai 		return badness;
1007352f7f91STakashi Iwai 	}
1008352f7f91STakashi Iwai 
1009352f7f91STakashi Iwai 	/* assign volume and mute controls */
1010352f7f91STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++)
1011352f7f91STakashi Iwai 		badness += assign_out_path_ctls(codec, spec->multi_io[i].pin,
1012352f7f91STakashi Iwai 						spec->multi_io[i].dac);
1013352f7f91STakashi Iwai 
1014352f7f91STakashi Iwai 	return badness;
1015352f7f91STakashi Iwai }
1016352f7f91STakashi Iwai 
1017352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1018352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1019352f7f91STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs)
1020352f7f91STakashi Iwai {
1021352f7f91STakashi Iwai 	int i;
1022352f7f91STakashi Iwai 	bool found = false;
1023352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
10240c8c0f56STakashi Iwai 		struct nid_path *path;
1025352f7f91STakashi Iwai 		hda_nid_t dac;
1026352f7f91STakashi Iwai 		if (dacs[i])
1027352f7f91STakashi Iwai 			continue;
1028352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1029352f7f91STakashi Iwai 		if (!dac)
1030352f7f91STakashi Iwai 			continue;
10310c8c0f56STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i], 0);
10320c8c0f56STakashi Iwai 		if (path) {
1033352f7f91STakashi Iwai 			dacs[i] = dac;
1034352f7f91STakashi Iwai 			found = true;
10350c8c0f56STakashi Iwai 			print_nid_path("output", path);
1036352f7f91STakashi Iwai 		}
1037352f7f91STakashi Iwai 	}
1038352f7f91STakashi Iwai 	return found;
1039352f7f91STakashi Iwai }
1040352f7f91STakashi Iwai 
1041352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1042352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1043352f7f91STakashi Iwai 			      bool fill_hardwired,
1044352f7f91STakashi Iwai 			      bool fill_mio_first)
1045352f7f91STakashi Iwai {
1046352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1047352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1048352f7f91STakashi Iwai 	int i, err, badness;
1049352f7f91STakashi Iwai 
1050352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1051352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1052352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1053352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1054352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1055352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1056352f7f91STakashi Iwai 	spec->multi_ios = 0;
1057352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1058352f7f91STakashi Iwai 	badness = 0;
1059352f7f91STakashi Iwai 
1060352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1061352f7f91STakashi Iwai 	if (fill_hardwired) {
1062352f7f91STakashi Iwai 		bool mapped;
1063352f7f91STakashi Iwai 		do {
1064352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1065352f7f91STakashi Iwai 					     cfg->line_out_pins,
1066352f7f91STakashi Iwai 					     spec->private_dac_nids);
1067352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1068352f7f91STakashi Iwai 					      cfg->hp_pins,
1069352f7f91STakashi Iwai 					      spec->multiout.hp_out_nid);
1070352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1071352f7f91STakashi Iwai 					      cfg->speaker_pins,
1072352f7f91STakashi Iwai 					      spec->multiout.extra_out_nid);
1073352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1074352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1075352f7f91STakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
1076352f7f91STakashi Iwai 				if (!err)
1077352f7f91STakashi Iwai 					mapped = true;
1078352f7f91STakashi Iwai 			}
1079352f7f91STakashi Iwai 		} while (mapped);
1080352f7f91STakashi Iwai 	}
1081352f7f91STakashi Iwai 
1082352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1083352f7f91STakashi Iwai 				   spec->private_dac_nids,
1084352f7f91STakashi Iwai 				   &main_out_badness);
1085352f7f91STakashi Iwai 
1086352f7f91STakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1087352f7f91STakashi Iwai 	spec->multiout.num_dacs = 0;
1088352f7f91STakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1089352f7f91STakashi Iwai 		if (spec->private_dac_nids[i])
1090352f7f91STakashi Iwai 			spec->multiout.num_dacs++;
1091352f7f91STakashi Iwai 		else {
1092352f7f91STakashi Iwai 			memmove(spec->private_dac_nids + i,
1093352f7f91STakashi Iwai 				spec->private_dac_nids + i + 1,
1094352f7f91STakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1095352f7f91STakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1096352f7f91STakashi Iwai 		}
1097352f7f91STakashi Iwai 	}
1098352f7f91STakashi Iwai 
1099352f7f91STakashi Iwai 	if (fill_mio_first &&
1100352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1101352f7f91STakashi Iwai 		/* try to fill multi-io first */
1102352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
1103352f7f91STakashi Iwai 		if (err < 0)
1104352f7f91STakashi Iwai 			return err;
1105352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1106352f7f91STakashi Iwai 	}
1107352f7f91STakashi Iwai 
1108352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1109352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1110352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1111352f7f91STakashi Iwai 				      &extra_out_badness);
1112352f7f91STakashi Iwai 		if (err < 0)
1113352f7f91STakashi Iwai 			return err;
1114352f7f91STakashi Iwai 		badness += err;
1115352f7f91STakashi Iwai 	}
1116352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1117352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1118352f7f91STakashi Iwai 				      cfg->speaker_pins,
1119352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1120352f7f91STakashi Iwai 					 &extra_out_badness);
1121352f7f91STakashi Iwai 		if (err < 0)
1122352f7f91STakashi Iwai 			return err;
1123352f7f91STakashi Iwai 		badness += err;
1124352f7f91STakashi Iwai 	}
1125352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1126352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
1127352f7f91STakashi Iwai 		if (err < 0)
1128352f7f91STakashi Iwai 			return err;
1129352f7f91STakashi Iwai 		badness += err;
1130352f7f91STakashi Iwai 	}
1131352f7f91STakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1132352f7f91STakashi Iwai 		/* try multi-ios with HP + inputs */
1133352f7f91STakashi Iwai 		int offset = 0;
1134352f7f91STakashi Iwai 		if (cfg->line_outs >= 3)
1135352f7f91STakashi Iwai 			offset = 1;
1136352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->hp_pins[0], false, offset);
1137352f7f91STakashi Iwai 		if (err < 0)
1138352f7f91STakashi Iwai 			return err;
1139352f7f91STakashi Iwai 		badness += err;
1140352f7f91STakashi Iwai 	}
1141352f7f91STakashi Iwai 
1142352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1143352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1144352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1145352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1146352f7f91STakashi Iwai 		spec->ext_channel_count = 2;
1147352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1148352f7f91STakashi Iwai 		spec->multi_ios = 0;
1149352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1150352f7f91STakashi Iwai 	}
1151352f7f91STakashi Iwai 
1152352f7f91STakashi Iwai 	return badness;
1153352f7f91STakashi Iwai }
1154352f7f91STakashi Iwai 
1155352f7f91STakashi Iwai #define DEBUG_BADNESS
1156352f7f91STakashi Iwai 
1157352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1158352f7f91STakashi Iwai #define debug_badness	snd_printdd
1159352f7f91STakashi Iwai #else
1160352f7f91STakashi Iwai #define debug_badness(...)
1161352f7f91STakashi Iwai #endif
1162352f7f91STakashi Iwai 
1163352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1164352f7f91STakashi Iwai {
1165352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1166352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1167708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1168352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1169352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1170352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1171352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1172352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1173352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1174352f7f91STakashi Iwai 			      spec->multi_ios,
1175352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1176352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1177352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1178352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1179708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1180352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1181352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1182352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1183352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1184352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1185352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1186352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1187352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1188352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1189352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1190352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1191352f7f91STakashi Iwai }
1192352f7f91STakashi Iwai 
1193352f7f91STakashi Iwai /* find all available DACs of the codec */
1194352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1195352f7f91STakashi Iwai {
1196352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1197352f7f91STakashi Iwai 	int i;
1198352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1199352f7f91STakashi Iwai 
1200352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1201352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1202352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1203352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1204352f7f91STakashi Iwai 			continue;
1205352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1206352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1207352f7f91STakashi Iwai 			break;
1208352f7f91STakashi Iwai 		}
1209352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1210352f7f91STakashi Iwai 	}
1211352f7f91STakashi Iwai }
1212352f7f91STakashi Iwai 
1213352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1214352f7f91STakashi Iwai {
1215352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1216352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1217352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1218352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1219352f7f91STakashi Iwai 	int badness;
1220352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1221352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1222352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1223352f7f91STakashi Iwai 
1224352f7f91STakashi Iwai 	fill_all_dac_nids(codec);
1225352f7f91STakashi Iwai 
1226352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1227352f7f91STakashi Iwai 	if (!best_cfg)
1228352f7f91STakashi Iwai 		return -ENOMEM;
1229352f7f91STakashi Iwai 	*best_cfg = *cfg;
1230352f7f91STakashi Iwai 
1231352f7f91STakashi Iwai 	for (;;) {
1232352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1233352f7f91STakashi Iwai 					     fill_mio_first);
1234352f7f91STakashi Iwai 		if (badness < 0) {
1235352f7f91STakashi Iwai 			kfree(best_cfg);
1236352f7f91STakashi Iwai 			return badness;
1237352f7f91STakashi Iwai 		}
1238352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1239352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1240352f7f91STakashi Iwai 			      badness);
1241352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1242352f7f91STakashi Iwai 		if (badness < best_badness) {
1243352f7f91STakashi Iwai 			best_badness = badness;
1244352f7f91STakashi Iwai 			*best_cfg = *cfg;
1245352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1246352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1247352f7f91STakashi Iwai 		}
1248352f7f91STakashi Iwai 		if (!badness)
1249352f7f91STakashi Iwai 			break;
1250352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1251352f7f91STakashi Iwai 		if (!fill_mio_first)
1252352f7f91STakashi Iwai 			continue;
1253352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1254352f7f91STakashi Iwai 		if (!fill_hardwired)
1255352f7f91STakashi Iwai 			continue;
1256352f7f91STakashi Iwai 		if (hp_spk_swapped)
1257352f7f91STakashi Iwai 			break;
1258352f7f91STakashi Iwai 		hp_spk_swapped = true;
1259352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1260352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1261352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1262352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1263352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1264352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1265352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1266352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1267352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1268352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1269352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1270352f7f91STakashi Iwai 			fill_hardwired = true;
1271352f7f91STakashi Iwai 			continue;
1272352f7f91STakashi Iwai 		}
1273352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1274352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1275352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1276352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1277352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1278352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1279352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1280352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1281352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1282352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1283352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1284352f7f91STakashi Iwai 			fill_hardwired = true;
1285352f7f91STakashi Iwai 			continue;
1286352f7f91STakashi Iwai 		}
1287352f7f91STakashi Iwai 		break;
1288352f7f91STakashi Iwai 	}
1289352f7f91STakashi Iwai 
1290352f7f91STakashi Iwai 	if (badness) {
12910c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1292352f7f91STakashi Iwai 		*cfg = *best_cfg;
1293352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1294352f7f91STakashi Iwai 	}
1295352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1296352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1297352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1298352f7f91STakashi Iwai 
1299352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1300352f7f91STakashi Iwai 		struct nid_path *path;
1301352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec,
1302352f7f91STakashi Iwai 					    spec->multiout.dac_nids[0],
1303352f7f91STakashi Iwai 					    cfg->line_out_pins[0]);
1304352f7f91STakashi Iwai 		if (path)
1305352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1306352f7f91STakashi Iwai 	}
1307352f7f91STakashi Iwai 
1308352f7f91STakashi Iwai 	kfree(best_cfg);
1309352f7f91STakashi Iwai 	return 0;
1310352f7f91STakashi Iwai }
1311352f7f91STakashi Iwai 
1312352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1313352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1314352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1315352f7f91STakashi Iwai {
1316352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1317352f7f91STakashi Iwai 	int i, err, noutputs;
1318352f7f91STakashi Iwai 
1319352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1320352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1321352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1322352f7f91STakashi Iwai 
1323352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1324352f7f91STakashi Iwai 		const char *name;
1325352f7f91STakashi Iwai 		int index;
1326352f7f91STakashi Iwai 		hda_nid_t dac, pin;
1327352f7f91STakashi Iwai 		struct nid_path *path;
1328352f7f91STakashi Iwai 
1329352f7f91STakashi Iwai 		dac = spec->multiout.dac_nids[i];
1330352f7f91STakashi Iwai 		if (!dac)
1331352f7f91STakashi Iwai 			continue;
1332352f7f91STakashi Iwai 		if (i >= cfg->line_outs) {
1333352f7f91STakashi Iwai 			pin = spec->multi_io[i - 1].pin;
1334352f7f91STakashi Iwai 			index = 0;
1335352f7f91STakashi Iwai 			name = channel_name[i];
1336352f7f91STakashi Iwai 		} else {
1337352f7f91STakashi Iwai 			pin = cfg->line_out_pins[i];
1338352f7f91STakashi Iwai 			name = get_line_out_pfx(spec, i, true, &index);
1339352f7f91STakashi Iwai 		}
1340352f7f91STakashi Iwai 
1341352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, dac, pin);
1342352f7f91STakashi Iwai 		if (!path)
1343352f7f91STakashi Iwai 			continue;
1344352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1345352f7f91STakashi Iwai 			/* Center/LFE */
1346352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1347352f7f91STakashi Iwai 			if (err < 0)
1348352f7f91STakashi Iwai 				return err;
1349352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1350352f7f91STakashi Iwai 			if (err < 0)
1351352f7f91STakashi Iwai 				return err;
1352352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1353352f7f91STakashi Iwai 			if (err < 0)
1354352f7f91STakashi Iwai 				return err;
1355352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1356352f7f91STakashi Iwai 			if (err < 0)
1357352f7f91STakashi Iwai 				return err;
1358352f7f91STakashi Iwai 		} else {
1359352f7f91STakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1360352f7f91STakashi Iwai 			if (err < 0)
1361352f7f91STakashi Iwai 				return err;
1362352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1363352f7f91STakashi Iwai 			if (err < 0)
1364352f7f91STakashi Iwai 				return err;
1365352f7f91STakashi Iwai 		}
1366352f7f91STakashi Iwai 	}
1367352f7f91STakashi Iwai 	return 0;
1368352f7f91STakashi Iwai }
1369352f7f91STakashi Iwai 
1370352f7f91STakashi Iwai static int create_extra_out(struct hda_codec *codec, hda_nid_t pin,
1371352f7f91STakashi Iwai 			    hda_nid_t dac, const char *pfx, int cidx)
1372352f7f91STakashi Iwai {
1373352f7f91STakashi Iwai 	struct nid_path *path;
1374352f7f91STakashi Iwai 	int err;
1375352f7f91STakashi Iwai 
1376352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, dac, pin);
1377352f7f91STakashi Iwai 	if (!path)
1378352f7f91STakashi Iwai 		return 0;
1379352f7f91STakashi Iwai 	/* bind volume control will be created in the case of dac = 0 */
1380352f7f91STakashi Iwai 	if (dac) {
1381352f7f91STakashi Iwai 		err = add_stereo_vol(codec, pfx, cidx, path);
1382352f7f91STakashi Iwai 		if (err < 0)
1383352f7f91STakashi Iwai 			return err;
1384352f7f91STakashi Iwai 	}
1385352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1386352f7f91STakashi Iwai 	if (err < 0)
1387352f7f91STakashi Iwai 		return err;
1388352f7f91STakashi Iwai 	return 0;
1389352f7f91STakashi Iwai }
1390352f7f91STakashi Iwai 
1391352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1392352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1393352f7f91STakashi Iwai 			     const hda_nid_t *pins, const hda_nid_t *dacs,
1394352f7f91STakashi Iwai 			     const char *pfx)
1395352f7f91STakashi Iwai {
1396352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1397352f7f91STakashi Iwai 	struct hda_bind_ctls *ctl;
1398352f7f91STakashi Iwai 	char name[32];
1399352f7f91STakashi Iwai 	int i, n, err;
1400352f7f91STakashi Iwai 
1401352f7f91STakashi Iwai 	if (!num_pins || !pins[0])
1402352f7f91STakashi Iwai 		return 0;
1403352f7f91STakashi Iwai 
1404352f7f91STakashi Iwai 	if (num_pins == 1) {
1405352f7f91STakashi Iwai 		hda_nid_t dac = *dacs;
1406352f7f91STakashi Iwai 		if (!dac)
1407352f7f91STakashi Iwai 			dac = spec->multiout.dac_nids[0];
1408352f7f91STakashi Iwai 		return create_extra_out(codec, *pins, dac, pfx, 0);
1409352f7f91STakashi Iwai 	}
1410352f7f91STakashi Iwai 
1411352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1412352f7f91STakashi Iwai 		hda_nid_t dac;
1413352f7f91STakashi Iwai 		if (dacs[num_pins - 1])
1414352f7f91STakashi Iwai 			dac = dacs[i]; /* with individual volumes */
1415352f7f91STakashi Iwai 		else
1416352f7f91STakashi Iwai 			dac = 0;
1417352f7f91STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
1418352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac,
1419352f7f91STakashi Iwai 					       "Bass Speaker", 0);
1420352f7f91STakashi Iwai 		} else if (num_pins >= 3) {
1421352f7f91STakashi Iwai 			snprintf(name, sizeof(name), "%s %s",
1422352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1423352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, name, 0);
1424352f7f91STakashi Iwai 		} else {
1425352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, pfx, i);
1426352f7f91STakashi Iwai 		}
1427352f7f91STakashi Iwai 		if (err < 0)
1428352f7f91STakashi Iwai 			return err;
1429352f7f91STakashi Iwai 	}
1430352f7f91STakashi Iwai 	if (dacs[num_pins - 1])
1431352f7f91STakashi Iwai 		return 0;
1432352f7f91STakashi Iwai 
1433352f7f91STakashi Iwai 	/* Let's create a bind-controls for volumes */
1434352f7f91STakashi Iwai 	ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
1435352f7f91STakashi Iwai 	if (!ctl)
1436352f7f91STakashi Iwai 		return -ENOMEM;
1437352f7f91STakashi Iwai 	n = 0;
1438352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1439352f7f91STakashi Iwai 		hda_nid_t vol;
1440352f7f91STakashi Iwai 		struct nid_path *path;
1441352f7f91STakashi Iwai 		if (!pins[i] || !dacs[i])
1442352f7f91STakashi Iwai 			continue;
1443352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, dacs[i], pins[i]);
1444352f7f91STakashi Iwai 		if (!path)
1445352f7f91STakashi Iwai 			continue;
1446352f7f91STakashi Iwai 		vol = look_for_out_vol_nid(codec, path);
1447352f7f91STakashi Iwai 		if (vol)
1448352f7f91STakashi Iwai 			ctl->values[n++] =
1449352f7f91STakashi Iwai 				HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
1450352f7f91STakashi Iwai 	}
1451352f7f91STakashi Iwai 	if (n) {
1452352f7f91STakashi Iwai 		snprintf(name, sizeof(name), "%s Playback Volume", pfx);
1453352f7f91STakashi Iwai 		err = add_control(spec, HDA_CTL_BIND_VOL, name, 0, (long)ctl);
1454352f7f91STakashi Iwai 		if (err < 0)
1455352f7f91STakashi Iwai 			return err;
1456352f7f91STakashi Iwai 	}
1457352f7f91STakashi Iwai 	return 0;
1458352f7f91STakashi Iwai }
1459352f7f91STakashi Iwai 
1460352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1461352f7f91STakashi Iwai {
1462352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1463352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1464352f7f91STakashi Iwai 				 spec->autocfg.hp_pins,
1465352f7f91STakashi Iwai 				 spec->multiout.hp_out_nid,
1466352f7f91STakashi Iwai 				 "Headphone");
1467352f7f91STakashi Iwai }
1468352f7f91STakashi Iwai 
1469352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1470352f7f91STakashi Iwai {
1471352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1472352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1473352f7f91STakashi Iwai 				 spec->autocfg.speaker_pins,
1474352f7f91STakashi Iwai 				 spec->multiout.extra_out_nid,
1475352f7f91STakashi Iwai 				 "Speaker");
1476352f7f91STakashi Iwai }
1477352f7f91STakashi Iwai 
1478352f7f91STakashi Iwai /*
1479352f7f91STakashi Iwai  * channel mode enum control
1480352f7f91STakashi Iwai  */
1481352f7f91STakashi Iwai 
1482352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1483352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1484352f7f91STakashi Iwai {
1485352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1486352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1487352f7f91STakashi Iwai 
1488352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1489352f7f91STakashi Iwai 	uinfo->count = 1;
1490352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1491352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1492352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1493352f7f91STakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch",
1494352f7f91STakashi Iwai 		(uinfo->value.enumerated.item + 1) * 2);
1495352f7f91STakashi Iwai 	return 0;
1496352f7f91STakashi Iwai }
1497352f7f91STakashi Iwai 
1498352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1499352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1500352f7f91STakashi Iwai {
1501352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1502352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1503352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
1504352f7f91STakashi Iwai 	return 0;
1505352f7f91STakashi Iwai }
1506352f7f91STakashi Iwai 
1507352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1508352f7f91STakashi Iwai {
1509352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1510352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1511352f7f91STakashi Iwai 	struct nid_path *path;
1512352f7f91STakashi Iwai 
1513352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->multi_io[idx].dac, nid);
1514352f7f91STakashi Iwai 	if (!path)
1515352f7f91STakashi Iwai 		return -EINVAL;
1516352f7f91STakashi Iwai 
1517352f7f91STakashi Iwai 	if (path->active == output)
1518352f7f91STakashi Iwai 		return 0;
1519352f7f91STakashi Iwai 
1520352f7f91STakashi Iwai 	if (output) {
1521352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
1522352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1523d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1524352f7f91STakashi Iwai 	} else {
1525d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1526352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
1527352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid,
1528352f7f91STakashi Iwai 					  spec->multi_io[idx].ctl_in);
1529352f7f91STakashi Iwai 	}
1530352f7f91STakashi Iwai 	return 0;
1531352f7f91STakashi Iwai }
1532352f7f91STakashi Iwai 
1533352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1534352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1535352f7f91STakashi Iwai {
1536352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1537352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1538352f7f91STakashi Iwai 	int i, ch;
1539352f7f91STakashi Iwai 
1540352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1541352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1542352f7f91STakashi Iwai 		return -EINVAL;
1543352f7f91STakashi Iwai 	if (ch == (spec->ext_channel_count - 1) / 2)
1544352f7f91STakashi Iwai 		return 0;
1545352f7f91STakashi Iwai 	spec->ext_channel_count = (ch + 1) * 2;
1546352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1547352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1548352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1549352f7f91STakashi Iwai 					  spec->const_channel_count);
1550352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1551352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1552352f7f91STakashi Iwai 	return 1;
1553352f7f91STakashi Iwai }
1554352f7f91STakashi Iwai 
1555352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1556352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557352f7f91STakashi Iwai 	.name = "Channel Mode",
1558352f7f91STakashi Iwai 	.info = ch_mode_info,
1559352f7f91STakashi Iwai 	.get = ch_mode_get,
1560352f7f91STakashi Iwai 	.put = ch_mode_put,
1561352f7f91STakashi Iwai };
1562352f7f91STakashi Iwai 
1563352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1564352f7f91STakashi Iwai {
1565352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1566352f7f91STakashi Iwai 
1567352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
156812c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1569352f7f91STakashi Iwai 			return -ENOMEM;
1570352f7f91STakashi Iwai 	}
1571352f7f91STakashi Iwai 	return 0;
1572352f7f91STakashi Iwai }
1573352f7f91STakashi Iwai 
1574352f7f91STakashi Iwai /*
1575352f7f91STakashi Iwai  * shared headphone/mic handling
1576352f7f91STakashi Iwai  */
1577352f7f91STakashi Iwai 
1578352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
1579352f7f91STakashi Iwai 
1580352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
1581352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
1582352f7f91STakashi Iwai {
1583352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1584352f7f91STakashi Iwai 	unsigned int val;
1585352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
1586352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
1587352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
1588352f7f91STakashi Iwai 	 */
1589352f7f91STakashi Iwai 
1590352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
1591352f7f91STakashi Iwai 
1592352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
1593352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
1594352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
1595352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
1596352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
1597352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
15987594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
15997594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
1600352f7f91STakashi Iwai 	}
1601352f7f91STakashi Iwai 
1602352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
16037594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, val);
1604352f7f91STakashi Iwai 
1605352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
1606352f7f91STakashi Iwai 	call_update_outputs(codec);
1607352f7f91STakashi Iwai }
1608352f7f91STakashi Iwai 
1609352f7f91STakashi Iwai /* create a shared input with the headphone out */
1610352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
1611352f7f91STakashi Iwai {
1612352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1613352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1614352f7f91STakashi Iwai 	unsigned int defcfg;
1615352f7f91STakashi Iwai 	hda_nid_t nid;
1616352f7f91STakashi Iwai 
1617352f7f91STakashi Iwai 	/* only one internal input pin? */
1618352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
1619352f7f91STakashi Iwai 		return 0;
1620352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
1621352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
1622352f7f91STakashi Iwai 		return 0;
1623352f7f91STakashi Iwai 
1624352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1625352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
1626352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
1627352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
1628352f7f91STakashi Iwai 	else
1629352f7f91STakashi Iwai 		return 0; /* both not available */
1630352f7f91STakashi Iwai 
1631352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
1632352f7f91STakashi Iwai 		return 0; /* no input */
1633352f7f91STakashi Iwai 
1634352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
1635352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
1636352f7f91STakashi Iwai 	cfg->num_inputs = 2;
1637352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
1638352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
1639352f7f91STakashi Iwai 	return 0;
1640352f7f91STakashi Iwai }
1641352f7f91STakashi Iwai 
1642352f7f91STakashi Iwai 
1643352f7f91STakashi Iwai /*
1644352f7f91STakashi Iwai  * Parse input paths
1645352f7f91STakashi Iwai  */
1646352f7f91STakashi Iwai 
1647352f7f91STakashi Iwai #ifdef CONFIG_PM
1648352f7f91STakashi Iwai /* add the powersave loopback-list entry */
1649352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
1650352f7f91STakashi Iwai {
1651352f7f91STakashi Iwai 	struct hda_amp_list *list;
1652352f7f91STakashi Iwai 
1653352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
1654352f7f91STakashi Iwai 		return;
1655352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
1656352f7f91STakashi Iwai 	list->nid = mix;
1657352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
1658352f7f91STakashi Iwai 	list->idx = idx;
1659352f7f91STakashi Iwai 	spec->num_loopbacks++;
1660cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
1661cb53c626STakashi Iwai }
1662cb53c626STakashi Iwai #else
1663352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
1664cb53c626STakashi Iwai #endif
1665cb53c626STakashi Iwai 
1666352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
1667352f7f91STakashi Iwai static int new_analog_input(struct hda_codec *codec, hda_nid_t pin,
1668352f7f91STakashi Iwai 			    const char *ctlname, int ctlidx,
1669352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
16701da177e4SLinus Torvalds {
1671352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1672352f7f91STakashi Iwai 	struct nid_path *path;
1673352f7f91STakashi Iwai 	unsigned int val;
1674352f7f91STakashi Iwai 	int err, idx;
16751da177e4SLinus Torvalds 
1676352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
1677352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
1678352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
1679352f7f91STakashi Iwai 
1680352f7f91STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 2);
1681352f7f91STakashi Iwai 	if (!path)
1682352f7f91STakashi Iwai 		return -EINVAL;
16830c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
1684352f7f91STakashi Iwai 
1685352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
1686352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
1687352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1688352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
1689d13bd412STakashi Iwai 		if (err < 0)
16901da177e4SLinus Torvalds 			return err;
1691352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
16921da177e4SLinus Torvalds 	}
16931da177e4SLinus Torvalds 
1694352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
1695352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1696352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
1697d13bd412STakashi Iwai 		if (err < 0)
16981da177e4SLinus Torvalds 			return err;
1699352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
17001da177e4SLinus Torvalds 	}
17011da177e4SLinus Torvalds 
1702352f7f91STakashi Iwai 	path->active = true;
1703352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
1704352f7f91STakashi Iwai 	return 0;
17051da177e4SLinus Torvalds }
17061da177e4SLinus Torvalds 
1707352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
17081da177e4SLinus Torvalds {
1709352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
1710352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
1711352f7f91STakashi Iwai }
1712352f7f91STakashi Iwai 
1713352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
1714352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
1715352f7f91STakashi Iwai {
1716352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1717352f7f91STakashi Iwai 	hda_nid_t nid;
1718352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
1719352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
1720352f7f91STakashi Iwai 	int i, nums = 0;
1721352f7f91STakashi Iwai 
1722352f7f91STakashi Iwai 	nid = codec->start_nid;
1723352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1724352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
1725352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
1726352f7f91STakashi Iwai 
1727352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
1728352f7f91STakashi Iwai 			continue;
1729352f7f91STakashi Iwai 		adc_nids[nums] = nid;
1730352f7f91STakashi Iwai 		if (++nums >= max_nums)
1731352f7f91STakashi Iwai 			break;
1732352f7f91STakashi Iwai 	}
1733352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
1734352f7f91STakashi Iwai 	return nums;
1735352f7f91STakashi Iwai }
1736352f7f91STakashi Iwai 
1737352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
1738352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
1739352f7f91STakashi Iwai  */
1740352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
1741352f7f91STakashi Iwai {
1742352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1743352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
1744352f7f91STakashi Iwai 	hda_nid_t adc_nids[ARRAY_SIZE(spec->adc_nids)];
1745352f7f91STakashi Iwai 	int i, n, nums;
1746352f7f91STakashi Iwai 	hda_nid_t pin, adc;
1747352f7f91STakashi Iwai 
1748352f7f91STakashi Iwai  again:
1749352f7f91STakashi Iwai 	nums = 0;
1750352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
1751352f7f91STakashi Iwai 		adc = spec->adc_nids[n];
1752352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1753352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1754352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
1755352f7f91STakashi Iwai 				break;
1756352f7f91STakashi Iwai 		}
1757352f7f91STakashi Iwai 		if (i >= imux->num_items)
1758352f7f91STakashi Iwai 			adc_nids[nums++] = adc;
1759352f7f91STakashi Iwai 	}
1760352f7f91STakashi Iwai 
1761352f7f91STakashi Iwai 	if (!nums) {
1762352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
1763352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
1764352f7f91STakashi Iwai 			imux->num_items = 1;
1765352f7f91STakashi Iwai 			goto again;
1766352f7f91STakashi Iwai 		}
1767352f7f91STakashi Iwai 
1768352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
1769352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1770352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1771352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
1772352f7f91STakashi Iwai 				adc = spec->adc_nids[n];
1773352f7f91STakashi Iwai 				if (is_reachable_path(codec, pin, adc)) {
1774352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
1775352f7f91STakashi Iwai 					break;
1776352f7f91STakashi Iwai 				}
1777352f7f91STakashi Iwai 			}
1778352f7f91STakashi Iwai 		}
1779352f7f91STakashi Iwai 
1780352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
1781352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
1782352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
1783352f7f91STakashi Iwai 		memcpy(spec->adc_nids, adc_nids, nums * sizeof(hda_nid_t));
1784352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
1785352f7f91STakashi Iwai 	}
1786352f7f91STakashi Iwai 
1787352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
1788352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
1789352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
1790352f7f91STakashi Iwai 	}
1791352f7f91STakashi Iwai 
1792352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
1793352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
1794352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
1795352f7f91STakashi Iwai 
17961da177e4SLinus Torvalds 	return 0;
17971da177e4SLinus Torvalds }
17981da177e4SLinus Torvalds 
17991da177e4SLinus Torvalds /*
1800352f7f91STakashi Iwai  * create playback/capture controls for input pins
18011da177e4SLinus Torvalds  */
1802352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
1803a7da6ce5STakashi Iwai {
1804352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1805352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
1806352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
1807352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
1808352f7f91STakashi Iwai 	int num_adcs;
1809352f7f91STakashi Iwai 	int i, c, err, type_idx = 0;
1810352f7f91STakashi Iwai 	const char *prev_label = NULL;
1811a7da6ce5STakashi Iwai 
1812352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
1813352f7f91STakashi Iwai 	if (num_adcs < 0)
1814352f7f91STakashi Iwai 		return 0;
1815352f7f91STakashi Iwai 
1816352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
1817352f7f91STakashi Iwai 		hda_nid_t pin;
1818352f7f91STakashi Iwai 		const char *label;
1819352f7f91STakashi Iwai 		bool imux_added;
1820352f7f91STakashi Iwai 
1821352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
1822352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
1823352f7f91STakashi Iwai 			continue;
1824352f7f91STakashi Iwai 
1825352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
1826352f7f91STakashi Iwai 		if (spec->shared_mic_hp && !strcmp(label, "Misc"))
1827352f7f91STakashi Iwai 			label = "Headphone Mic";
1828352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
1829352f7f91STakashi Iwai 			type_idx++;
1830352f7f91STakashi Iwai 		else
1831352f7f91STakashi Iwai 			type_idx = 0;
1832352f7f91STakashi Iwai 		prev_label = label;
1833352f7f91STakashi Iwai 
1834352f7f91STakashi Iwai 		if (mixer) {
1835352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
1836352f7f91STakashi Iwai 				err = new_analog_input(codec, pin,
1837352f7f91STakashi Iwai 						       label, type_idx, mixer);
1838a7da6ce5STakashi Iwai 				if (err < 0)
1839a7da6ce5STakashi Iwai 					return err;
1840a7da6ce5STakashi Iwai 			}
1841352f7f91STakashi Iwai 		}
1842352f7f91STakashi Iwai 
1843352f7f91STakashi Iwai 		imux_added = false;
1844352f7f91STakashi Iwai 		for (c = 0; c < num_adcs; c++) {
1845352f7f91STakashi Iwai 			struct nid_path *path;
1846352f7f91STakashi Iwai 			hda_nid_t adc = spec->adc_nids[c];
1847352f7f91STakashi Iwai 
1848352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
1849352f7f91STakashi Iwai 				continue;
1850352f7f91STakashi Iwai 			path = snd_array_new(&spec->paths);
1851352f7f91STakashi Iwai 			if (!path)
1852352f7f91STakashi Iwai 				return -ENOMEM;
1853352f7f91STakashi Iwai 			memset(path, 0, sizeof(*path));
1854352f7f91STakashi Iwai 			if (!snd_hda_parse_nid_path(codec, pin, adc, 2, path)) {
1855352f7f91STakashi Iwai 				snd_printd(KERN_ERR
1856352f7f91STakashi Iwai 					   "invalid input path 0x%x -> 0x%x\n",
1857352f7f91STakashi Iwai 					   pin, adc);
1858352f7f91STakashi Iwai 				spec->paths.used--;
1859352f7f91STakashi Iwai 				continue;
1860352f7f91STakashi Iwai 			}
18610c8c0f56STakashi Iwai 			print_nid_path("input", path);
1862352f7f91STakashi Iwai 
1863352f7f91STakashi Iwai 			if (!imux_added) {
1864352f7f91STakashi Iwai 				spec->imux_pins[imux->num_items] = pin;
1865352f7f91STakashi Iwai 				snd_hda_add_imux_item(imux, label,
1866352f7f91STakashi Iwai 						      imux->num_items, NULL);
1867352f7f91STakashi Iwai 				imux_added = true;
1868352f7f91STakashi Iwai 			}
1869352f7f91STakashi Iwai 		}
1870352f7f91STakashi Iwai 	}
1871352f7f91STakashi Iwai 
1872a7da6ce5STakashi Iwai 	return 0;
1873a7da6ce5STakashi Iwai }
1874a7da6ce5STakashi Iwai 
18751da177e4SLinus Torvalds 
1876352f7f91STakashi Iwai /*
1877352f7f91STakashi Iwai  * input source mux
1878352f7f91STakashi Iwai  */
1879352f7f91STakashi Iwai 
1880352f7f91STakashi Iwai /* get the ADC NID corresponding to the given index */
1881352f7f91STakashi Iwai static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
1882352f7f91STakashi Iwai {
1883352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1884352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
1885352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
1886352f7f91STakashi Iwai 	return spec->adc_nids[adc_idx];
188797ec558aSTakashi Iwai }
1888352f7f91STakashi Iwai 
1889352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
1890352f7f91STakashi Iwai 		      unsigned int idx);
1891352f7f91STakashi Iwai 
1892352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
1893352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
1894352f7f91STakashi Iwai {
1895352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1896352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1897352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
1898352f7f91STakashi Iwai }
1899352f7f91STakashi Iwai 
1900352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
1901352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
1902352f7f91STakashi Iwai {
1903352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1904352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1905352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1906352f7f91STakashi Iwai 
1907352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
19081da177e4SLinus Torvalds 	return 0;
19091da177e4SLinus Torvalds }
19101da177e4SLinus Torvalds 
1911352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
1912352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
19131da177e4SLinus Torvalds {
1914352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1915352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1916352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
1917352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
1918352f7f91STakashi Iwai }
1919352f7f91STakashi Iwai 
1920352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
19211da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1922352f7f91STakashi Iwai 	.name = "Input Source",
1923352f7f91STakashi Iwai 	.info = mux_enum_info,
1924352f7f91STakashi Iwai 	.get = mux_enum_get,
1925352f7f91STakashi Iwai 	.put = mux_enum_put,
19261da177e4SLinus Torvalds };
1927071c73adSTakashi Iwai 
192847d46abbSTakashi Iwai /*
192947d46abbSTakashi Iwai  * capture volume and capture switch ctls
193047d46abbSTakashi Iwai  */
193147d46abbSTakashi Iwai 
1932352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
1933352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
1934071c73adSTakashi Iwai 
193547d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
1936352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
1937352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
1938352f7f91STakashi Iwai 			  put_call_t func, int type)
1939352f7f91STakashi Iwai {
1940352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1941352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1942352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
1943352f7f91STakashi Iwai 	struct nid_path *path;
1944352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
1945071c73adSTakashi Iwai 
1946352f7f91STakashi Iwai 	imux = &spec->input_mux;
1947352f7f91STakashi Iwai 	adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1948352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
194947d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
195047d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
195147d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
195247d46abbSTakashi Iwai 	 */
1953352f7f91STakashi Iwai 	codec->cached_write = 1;
1954352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
1955352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
1956352f7f91STakashi Iwai 					    get_adc_nid(codec, adc_idx, i));
1957352f7f91STakashi Iwai 		if (!path->ctls[type])
1958352f7f91STakashi Iwai 			continue;
1959352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
1960352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
1961352f7f91STakashi Iwai 		if (err < 0)
1962352f7f91STakashi Iwai 			goto error;
1963352f7f91STakashi Iwai 	}
1964352f7f91STakashi Iwai  error:
1965352f7f91STakashi Iwai 	codec->cached_write = 0;
1966352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
196747d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
1968352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
1969352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
1970352f7f91STakashi Iwai 	return err;
1971352f7f91STakashi Iwai }
1972352f7f91STakashi Iwai 
1973352f7f91STakashi Iwai /* capture volume ctl callbacks */
1974352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
1975352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
1976352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
1977352f7f91STakashi Iwai 
1978352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
1979352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1980352f7f91STakashi Iwai {
1981352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
1982352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
1983352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
1984352f7f91STakashi Iwai }
1985352f7f91STakashi Iwai 
1986352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
1987352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1988352f7f91STakashi Iwai 	.name = "Capture Volume",
1989352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1990352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1991352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
1992352f7f91STakashi Iwai 	.info = cap_vol_info,
1993352f7f91STakashi Iwai 	.get = cap_vol_get,
1994352f7f91STakashi Iwai 	.put = cap_vol_put,
1995352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
1996352f7f91STakashi Iwai };
1997352f7f91STakashi Iwai 
1998352f7f91STakashi Iwai /* capture switch ctl callbacks */
1999352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2000352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2001352f7f91STakashi Iwai 
2002352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2003352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2004352f7f91STakashi Iwai {
2005352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2006352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2007352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2008352f7f91STakashi Iwai }
2009352f7f91STakashi Iwai 
2010352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2011352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2012352f7f91STakashi Iwai 	.name = "Capture Switch",
2013352f7f91STakashi Iwai 	.info = cap_sw_info,
2014352f7f91STakashi Iwai 	.get = cap_sw_get,
2015352f7f91STakashi Iwai 	.put = cap_sw_put,
2016352f7f91STakashi Iwai };
2017352f7f91STakashi Iwai 
2018352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2019352f7f91STakashi Iwai {
2020352f7f91STakashi Iwai 	hda_nid_t nid;
2021352f7f91STakashi Iwai 	int i, depth;
2022352f7f91STakashi Iwai 
2023352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2024352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2025352f7f91STakashi Iwai 		if (depth >= path->depth)
2026352f7f91STakashi Iwai 			return -EINVAL;
2027352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2028352f7f91STakashi Iwai 		nid = path->path[i];
2029352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2030352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2031352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2032352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2033352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2034352f7f91STakashi Iwai 				int idx = path->idx[i];
2035352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2036352f7f91STakashi Iwai 					idx = 0;
2037352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2038352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2039352f7f91STakashi Iwai 			}
2040352f7f91STakashi Iwai 		}
2041352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2042352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2043352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2044352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2045352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2046352f7f91STakashi Iwai 				int idx = path->idx[i];
2047352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2048352f7f91STakashi Iwai 					idx = 0;
2049352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2050352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2051352f7f91STakashi Iwai 			}
2052352f7f91STakashi Iwai 		}
2053352f7f91STakashi Iwai 	}
2054352f7f91STakashi Iwai 	return 0;
2055352f7f91STakashi Iwai }
2056352f7f91STakashi Iwai 
2057352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2058352f7f91STakashi Iwai {
2059352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2060352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2061352f7f91STakashi Iwai 	unsigned int val;
2062352f7f91STakashi Iwai 	int i;
2063352f7f91STakashi Iwai 
2064352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2065352f7f91STakashi Iwai 		return false;
2066352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2067352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2068352f7f91STakashi Iwai 			continue;
2069352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2070352f7f91STakashi Iwai 			return false;
2071352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2072352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2073352f7f91STakashi Iwai 	}
2074352f7f91STakashi Iwai 	return false;
2075352f7f91STakashi Iwai }
2076352f7f91STakashi Iwai 
2077352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2078352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2079352f7f91STakashi Iwai 			      bool inv_dmic)
2080352f7f91STakashi Iwai {
2081352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2082352f7f91STakashi Iwai 	char tmpname[44];
2083352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2084352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2085352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2086352f7f91STakashi Iwai 	int err;
2087352f7f91STakashi Iwai 
2088352f7f91STakashi Iwai 	if (!ctl)
2089352f7f91STakashi Iwai 		return 0;
2090352f7f91STakashi Iwai 
2091352f7f91STakashi Iwai 	if (label)
2092352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2093352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2094352f7f91STakashi Iwai 	else
2095352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2096352f7f91STakashi Iwai 			 "Capture %s", sfx);
2097352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2098352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2099352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2100352f7f91STakashi Iwai 		return err;
2101352f7f91STakashi Iwai 
2102352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2103352f7f91STakashi Iwai 	if (label)
2104352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2105352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2106352f7f91STakashi Iwai 	else
2107352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2108352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2109352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2110352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2111352f7f91STakashi Iwai }
2112352f7f91STakashi Iwai 
2113352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2114352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2115352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2116352f7f91STakashi Iwai 				     bool inv_dmic)
2117352f7f91STakashi Iwai {
2118352f7f91STakashi Iwai 	int err;
2119352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2120352f7f91STakashi Iwai 	if (err < 0)
2121352f7f91STakashi Iwai 		return err;
2122352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2123071c73adSTakashi Iwai 	if (err < 0)
2124071c73adSTakashi Iwai 		return err;
2125071c73adSTakashi Iwai 	return 0;
21261da177e4SLinus Torvalds }
2127071c73adSTakashi Iwai 
2128352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2129352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2130352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2131352f7f91STakashi Iwai {
2132352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2133352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2134352f7f91STakashi Iwai 
2135352f7f91STakashi Iwai 	if (vol_ctl) {
213612c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2137352f7f91STakashi Iwai 		if (!knew)
2138352f7f91STakashi Iwai 			return -ENOMEM;
2139352f7f91STakashi Iwai 		knew->index = idx;
2140352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2141352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2142352f7f91STakashi Iwai 	}
2143352f7f91STakashi Iwai 	if (sw_ctl) {
214412c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2145352f7f91STakashi Iwai 		if (!knew)
2146352f7f91STakashi Iwai 			return -ENOMEM;
2147352f7f91STakashi Iwai 		knew->index = idx;
2148352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2149352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2150352f7f91STakashi Iwai 	}
2151352f7f91STakashi Iwai 	return 0;
2152352f7f91STakashi Iwai }
2153352f7f91STakashi Iwai 
2154352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2155352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2156352f7f91STakashi Iwai {
2157352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2158352f7f91STakashi Iwai 	struct nid_path *path;
2159352f7f91STakashi Iwai 	unsigned int ctl;
2160352f7f91STakashi Iwai 	int i;
2161352f7f91STakashi Iwai 
2162352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2163352f7f91STakashi Iwai 				    get_adc_nid(codec, 0, idx));
2164352f7f91STakashi Iwai 	if (!path)
2165352f7f91STakashi Iwai 		return 0;
2166352f7f91STakashi Iwai 	ctl = path->ctls[type];
2167352f7f91STakashi Iwai 	if (!ctl)
2168352f7f91STakashi Iwai 		return 0;
2169352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2170352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2171352f7f91STakashi Iwai 					    get_adc_nid(codec, 0, i));
2172352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2173352f7f91STakashi Iwai 			return 0;
2174352f7f91STakashi Iwai 	}
2175352f7f91STakashi Iwai 	return ctl;
2176352f7f91STakashi Iwai }
2177352f7f91STakashi Iwai 
2178352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2179352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2180352f7f91STakashi Iwai {
2181352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2182352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2183352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2184352f7f91STakashi Iwai 	const char *prev_label = NULL;
2185352f7f91STakashi Iwai 
2186352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2187352f7f91STakashi Iwai 		const char *label;
2188352f7f91STakashi Iwai 		bool inv_dmic;
2189352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
2190352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2191352f7f91STakashi Iwai 			type_idx++;
2192352f7f91STakashi Iwai 		else
2193352f7f91STakashi Iwai 			type_idx = 0;
2194352f7f91STakashi Iwai 		prev_label = label;
2195352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2196352f7f91STakashi Iwai 
2197352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2198352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2199352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2200352f7f91STakashi Iwai 						 inv_dmic);
2201d13bd412STakashi Iwai 			if (err < 0)
2202071c73adSTakashi Iwai 				return err;
2203352f7f91STakashi Iwai 		}
2204352f7f91STakashi Iwai 	}
2205071c73adSTakashi Iwai 	return 0;
2206352f7f91STakashi Iwai }
2207071c73adSTakashi Iwai 
2208352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2209352f7f91STakashi Iwai {
2210352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2211352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2212352f7f91STakashi Iwai 	int i, n, nums, err;
2213352f7f91STakashi Iwai 
2214352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2215352f7f91STakashi Iwai 		nums = 1;
2216352f7f91STakashi Iwai 	else
2217352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2218352f7f91STakashi Iwai 
2219352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2220352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2221624d914dSTakashi Iwai 		const char *name;
2222624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2223624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2224352f7f91STakashi Iwai 		if (!knew)
2225352f7f91STakashi Iwai 			return -ENOMEM;
2226352f7f91STakashi Iwai 		knew->count = nums;
2227352f7f91STakashi Iwai 	}
2228352f7f91STakashi Iwai 
2229352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2230352f7f91STakashi Iwai 		bool multi = false;
2231352f7f91STakashi Iwai 		bool inv_dmic = false;
2232352f7f91STakashi Iwai 		int vol, sw;
2233352f7f91STakashi Iwai 
2234352f7f91STakashi Iwai 		vol = sw = 0;
2235352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2236352f7f91STakashi Iwai 			struct nid_path *path;
2237352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2238352f7f91STakashi Iwai 						    get_adc_nid(codec, n, i));
2239352f7f91STakashi Iwai 			if (!path)
2240352f7f91STakashi Iwai 				continue;
2241352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2242352f7f91STakashi Iwai 			if (!vol)
2243352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
2244352f7f91STakashi Iwai 			else if (vol != path->ctls[NID_PATH_VOL_CTL])
2245352f7f91STakashi Iwai 				multi = true;
2246352f7f91STakashi Iwai 			if (!sw)
2247352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
2248352f7f91STakashi Iwai 			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
2249352f7f91STakashi Iwai 				multi = true;
2250352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2251352f7f91STakashi Iwai 				inv_dmic = true;
2252352f7f91STakashi Iwai 		}
2253352f7f91STakashi Iwai 
2254352f7f91STakashi Iwai 		if (!multi)
2255352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2256352f7f91STakashi Iwai 							inv_dmic);
2257352f7f91STakashi Iwai 		else if (!spec->multi_cap_vol)
2258352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2259352f7f91STakashi Iwai 		else
2260352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
2261d13bd412STakashi Iwai 		if (err < 0)
2262071c73adSTakashi Iwai 			return err;
2263071c73adSTakashi Iwai 	}
2264071c73adSTakashi Iwai 
22651da177e4SLinus Torvalds 	return 0;
22661da177e4SLinus Torvalds }
22671da177e4SLinus Torvalds 
2268352f7f91STakashi Iwai /*
2269352f7f91STakashi Iwai  * add mic boosts if needed
2270352f7f91STakashi Iwai  */
2271352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
2272352f7f91STakashi Iwai {
2273352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2274352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2275352f7f91STakashi Iwai 	int i, err;
2276352f7f91STakashi Iwai 	int type_idx = 0;
2277352f7f91STakashi Iwai 	hda_nid_t nid;
2278352f7f91STakashi Iwai 	const char *prev_label = NULL;
2279352f7f91STakashi Iwai 
2280352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2281352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
2282352f7f91STakashi Iwai 			break;
2283352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
2284352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
2285352f7f91STakashi Iwai 			const char *label;
2286352f7f91STakashi Iwai 			char boost_label[32];
2287352f7f91STakashi Iwai 			struct nid_path *path;
2288352f7f91STakashi Iwai 			unsigned int val;
2289352f7f91STakashi Iwai 
2290352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
2291352f7f91STakashi Iwai 			if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2292352f7f91STakashi Iwai 				label = "Headphone Mic";
2293352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
2294352f7f91STakashi Iwai 				type_idx++;
2295352f7f91STakashi Iwai 			else
2296352f7f91STakashi Iwai 				type_idx = 0;
2297352f7f91STakashi Iwai 			prev_label = label;
2298352f7f91STakashi Iwai 
2299352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
2300352f7f91STakashi Iwai 				 "%s Boost Volume", label);
2301352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
2302352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
2303352f7f91STakashi Iwai 					  boost_label, type_idx, val);
2304352f7f91STakashi Iwai 			if (err < 0)
2305352f7f91STakashi Iwai 				return err;
2306352f7f91STakashi Iwai 
2307352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
2308352f7f91STakashi Iwai 			if (path)
2309352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
2310352f7f91STakashi Iwai 		}
2311352f7f91STakashi Iwai 	}
2312352f7f91STakashi Iwai 	return 0;
2313352f7f91STakashi Iwai }
2314352f7f91STakashi Iwai 
2315352f7f91STakashi Iwai /*
2316352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
2317352f7f91STakashi Iwai  */
2318352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
2319352f7f91STakashi Iwai {
2320352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
23210c8c0f56STakashi Iwai 	struct nid_path *path;
2322352f7f91STakashi Iwai 	int i, nums;
2323352f7f91STakashi Iwai 	hda_nid_t dig_nid;
2324352f7f91STakashi Iwai 
2325352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
2326352f7f91STakashi Iwai 	nums = 0;
2327352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
2328352f7f91STakashi Iwai 		hda_nid_t pin = spec->autocfg.dig_out_pins[i];
2329352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
2330352f7f91STakashi Iwai 		if (!dig_nid)
2331352f7f91STakashi Iwai 			continue;
23320c8c0f56STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 2);
23330c8c0f56STakashi Iwai 		if (!path)
2334352f7f91STakashi Iwai 			continue;
23350c8c0f56STakashi Iwai 		print_nid_path("digout", path);
2336352f7f91STakashi Iwai 		if (!nums) {
2337352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
2338352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
2339352f7f91STakashi Iwai 		} else {
2340352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2341352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2342352f7f91STakashi Iwai 			break;
2343352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
2344352f7f91STakashi Iwai 		}
2345352f7f91STakashi Iwai 		nums++;
2346352f7f91STakashi Iwai 	}
2347352f7f91STakashi Iwai 
2348352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
2349352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
2350352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2351352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
2352352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2353352f7f91STakashi Iwai 				continue;
2354352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
2355352f7f91STakashi Iwai 				continue;
2356352f7f91STakashi Iwai 			path = snd_hda_add_new_path(codec,
2357352f7f91STakashi Iwai 						    spec->autocfg.dig_in_pin,
2358352f7f91STakashi Iwai 						    dig_nid, 2);
2359352f7f91STakashi Iwai 			if (path) {
23600c8c0f56STakashi Iwai 				print_nid_path("digin", path);
2361352f7f91STakashi Iwai 				path->active = true;
2362352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
2363352f7f91STakashi Iwai 				break;
2364352f7f91STakashi Iwai 			}
2365352f7f91STakashi Iwai 		}
2366352f7f91STakashi Iwai 	}
2367352f7f91STakashi Iwai }
2368352f7f91STakashi Iwai 
23691da177e4SLinus Torvalds 
23701da177e4SLinus Torvalds /*
2371352f7f91STakashi Iwai  * input MUX handling
23721da177e4SLinus Torvalds  */
23731da177e4SLinus Torvalds 
2374352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
2375352f7f91STakashi Iwai 
2376352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
2377352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2378352f7f91STakashi Iwai 		      unsigned int idx)
2379352f7f91STakashi Iwai {
2380352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2381352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2382352f7f91STakashi Iwai 	struct nid_path *path;
2383352f7f91STakashi Iwai 
2384352f7f91STakashi Iwai 	imux = &spec->input_mux;
2385352f7f91STakashi Iwai 	if (!imux->num_items)
23861da177e4SLinus Torvalds 		return 0;
23871da177e4SLinus Torvalds 
2388352f7f91STakashi Iwai 	if (idx >= imux->num_items)
2389352f7f91STakashi Iwai 		idx = imux->num_items - 1;
2390352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
2391352f7f91STakashi Iwai 		return 0;
2392352f7f91STakashi Iwai 
2393352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec,
2394352f7f91STakashi Iwai 				    spec->imux_pins[spec->cur_mux[adc_idx]],
2395352f7f91STakashi Iwai 				    spec->adc_nids[adc_idx]);
2396352f7f91STakashi Iwai 	if (!path)
2397352f7f91STakashi Iwai 		return 0;
2398352f7f91STakashi Iwai 	if (path->active)
2399352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
2400352f7f91STakashi Iwai 
2401352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
2402352f7f91STakashi Iwai 
2403352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
2404352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
2405352f7f91STakashi Iwai 
2406352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2407352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
2408352f7f91STakashi Iwai 
2409352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2410352f7f91STakashi Iwai 				    get_adc_nid(codec, adc_idx, idx));
2411352f7f91STakashi Iwai 	if (!path)
2412352f7f91STakashi Iwai 		return 0;
2413352f7f91STakashi Iwai 	if (path->active)
2414352f7f91STakashi Iwai 		return 0;
2415352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
2416352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
2417352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
24181da177e4SLinus Torvalds 	return 1;
24191da177e4SLinus Torvalds }
24201da177e4SLinus Torvalds 
24211da177e4SLinus Torvalds 
24221da177e4SLinus Torvalds /*
2423352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
24241da177e4SLinus Torvalds  */
2425352f7f91STakashi Iwai 
2426352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
2427352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
24281da177e4SLinus Torvalds {
2429352f7f91STakashi Iwai 	int i, present = 0;
24301da177e4SLinus Torvalds 
2431352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2432352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2433352f7f91STakashi Iwai 		if (!nid)
2434352f7f91STakashi Iwai 			break;
2435352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
24361da177e4SLinus Torvalds 	}
2437352f7f91STakashi Iwai 	return present;
24381da177e4SLinus Torvalds }
24391da177e4SLinus Torvalds 
2440352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
2441352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
2442352f7f91STakashi Iwai 			bool mute, bool hp_out)
24431da177e4SLinus Torvalds {
2444352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2445352f7f91STakashi Iwai 	unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
2446352f7f91STakashi Iwai 	int i;
24471da177e4SLinus Torvalds 
2448352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2449352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2450352f7f91STakashi Iwai 		unsigned int val;
2451352f7f91STakashi Iwai 		if (!nid)
2452352f7f91STakashi Iwai 			break;
2453352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
2454352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
2455352f7f91STakashi Iwai 		 */
2456352f7f91STakashi Iwai 		if (spec->keep_vref_in_automute) {
2457352f7f91STakashi Iwai 			val = snd_hda_codec_read(codec, nid, 0,
2458352f7f91STakashi Iwai 					AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2459352f7f91STakashi Iwai 			val &= ~PIN_HP;
2460352f7f91STakashi Iwai 		} else
2461352f7f91STakashi Iwai 			val = 0;
2462352f7f91STakashi Iwai 		val |= pin_bits;
24637594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, val);
2464d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
2465352f7f91STakashi Iwai 	}
2466352f7f91STakashi Iwai }
24671da177e4SLinus Torvalds 
2468352f7f91STakashi Iwai /* Toggle outputs muting */
24695d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
2470352f7f91STakashi Iwai {
2471352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2472352f7f91STakashi Iwai 	int on;
2473352f7f91STakashi Iwai 
2474352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
2475352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
2476352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
2477352f7f91STakashi Iwai 	 */
2478352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
2479352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2480352f7f91STakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute, true);
2481352f7f91STakashi Iwai 
2482352f7f91STakashi Iwai 	if (!spec->automute_speaker)
2483352f7f91STakashi Iwai 		on = 0;
2484352f7f91STakashi Iwai 	else
2485352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
2486352f7f91STakashi Iwai 	on |= spec->master_mute;
2487352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
2488352f7f91STakashi Iwai 		    spec->autocfg.speaker_pins, on, false);
2489352f7f91STakashi Iwai 
2490352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
2491352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
2492352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
2493352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
2494352f7f91STakashi Iwai 		return;
2495352f7f91STakashi Iwai 	if (!spec->automute_lo)
2496352f7f91STakashi Iwai 		on = 0;
2497352f7f91STakashi Iwai 	else
2498352f7f91STakashi Iwai 		on = spec->hp_jack_present;
2499352f7f91STakashi Iwai 	on |= spec->master_mute;
2500352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2501352f7f91STakashi Iwai 		    spec->autocfg.line_out_pins, on, false);
2502352f7f91STakashi Iwai }
25035d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
2504352f7f91STakashi Iwai 
2505352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
2506352f7f91STakashi Iwai {
2507352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2508352f7f91STakashi Iwai 	if (spec->automute_hook)
2509352f7f91STakashi Iwai 		spec->automute_hook(codec);
2510352f7f91STakashi Iwai 	else
25115d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
2512352f7f91STakashi Iwai }
2513352f7f91STakashi Iwai 
2514352f7f91STakashi Iwai /* standard HP-automute helper */
25155d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2516352f7f91STakashi Iwai {
2517352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2518352f7f91STakashi Iwai 
2519352f7f91STakashi Iwai 	spec->hp_jack_present =
2520352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2521352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
2522352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
2523352f7f91STakashi Iwai 		return;
2524352f7f91STakashi Iwai 	call_update_outputs(codec);
2525352f7f91STakashi Iwai }
25265d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
2527352f7f91STakashi Iwai 
2528352f7f91STakashi Iwai /* standard line-out-automute helper */
25295d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2530352f7f91STakashi Iwai {
2531352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2532352f7f91STakashi Iwai 
2533352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
2534352f7f91STakashi Iwai 		return;
2535352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
2536352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
2537352f7f91STakashi Iwai 		return;
2538352f7f91STakashi Iwai 
2539352f7f91STakashi Iwai 	spec->line_jack_present =
2540352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2541352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
2542352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
2543352f7f91STakashi Iwai 		return;
2544352f7f91STakashi Iwai 	call_update_outputs(codec);
2545352f7f91STakashi Iwai }
25465d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
2547352f7f91STakashi Iwai 
2548352f7f91STakashi Iwai /* standard mic auto-switch helper */
25495d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
2550352f7f91STakashi Iwai {
2551352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2552352f7f91STakashi Iwai 	int i;
2553352f7f91STakashi Iwai 
2554352f7f91STakashi Iwai 	if (!spec->auto_mic)
2555352f7f91STakashi Iwai 		return;
2556352f7f91STakashi Iwai 
2557352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
2558352f7f91STakashi Iwai 		if (snd_hda_jack_detect(codec, spec->am_entry[i].pin)) {
2559352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
2560352f7f91STakashi Iwai 			return;
2561352f7f91STakashi Iwai 		}
2562352f7f91STakashi Iwai 	}
2563352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
25641da177e4SLinus Torvalds }
25655d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
25661da177e4SLinus Torvalds 
25671da177e4SLinus Torvalds /*
2568352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
25691da177e4SLinus Torvalds  */
2570352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
2571352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2572352f7f91STakashi Iwai {
2573352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2574352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2575352f7f91STakashi Iwai 	static const char * const texts3[] = {
2576352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
25771da177e4SLinus Torvalds 	};
25781da177e4SLinus Torvalds 
2579352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
2580352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
2581352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
2582352f7f91STakashi Iwai }
2583352f7f91STakashi Iwai 
2584352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
2585352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2586352f7f91STakashi Iwai {
2587352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2588352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2589352f7f91STakashi Iwai 	unsigned int val = 0;
2590352f7f91STakashi Iwai 	if (spec->automute_speaker)
2591352f7f91STakashi Iwai 		val++;
2592352f7f91STakashi Iwai 	if (spec->automute_lo)
2593352f7f91STakashi Iwai 		val++;
2594352f7f91STakashi Iwai 
2595352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
2596352f7f91STakashi Iwai 	return 0;
2597352f7f91STakashi Iwai }
2598352f7f91STakashi Iwai 
2599352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
2600352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2601352f7f91STakashi Iwai {
2602352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2603352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2604352f7f91STakashi Iwai 
2605352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
2606352f7f91STakashi Iwai 	case 0:
2607352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
2608352f7f91STakashi Iwai 			return 0;
2609352f7f91STakashi Iwai 		spec->automute_speaker = 0;
2610352f7f91STakashi Iwai 		spec->automute_lo = 0;
2611352f7f91STakashi Iwai 		break;
2612352f7f91STakashi Iwai 	case 1:
2613352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
2614352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
2615352f7f91STakashi Iwai 				return 0;
2616352f7f91STakashi Iwai 			spec->automute_speaker = 1;
2617352f7f91STakashi Iwai 			spec->automute_lo = 0;
2618352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
2619352f7f91STakashi Iwai 			if (spec->automute_lo)
2620352f7f91STakashi Iwai 				return 0;
2621352f7f91STakashi Iwai 			spec->automute_lo = 1;
2622352f7f91STakashi Iwai 		} else
2623352f7f91STakashi Iwai 			return -EINVAL;
2624352f7f91STakashi Iwai 		break;
2625352f7f91STakashi Iwai 	case 2:
2626352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
2627352f7f91STakashi Iwai 			return -EINVAL;
2628352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
2629352f7f91STakashi Iwai 			return 0;
2630352f7f91STakashi Iwai 		spec->automute_speaker = 1;
2631352f7f91STakashi Iwai 		spec->automute_lo = 1;
2632352f7f91STakashi Iwai 		break;
2633352f7f91STakashi Iwai 	default:
2634352f7f91STakashi Iwai 		return -EINVAL;
2635352f7f91STakashi Iwai 	}
2636352f7f91STakashi Iwai 	call_update_outputs(codec);
2637352f7f91STakashi Iwai 	return 1;
2638352f7f91STakashi Iwai }
2639352f7f91STakashi Iwai 
2640352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
2641352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2642352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
2643352f7f91STakashi Iwai 	.info = automute_mode_info,
2644352f7f91STakashi Iwai 	.get = automute_mode_get,
2645352f7f91STakashi Iwai 	.put = automute_mode_put,
2646352f7f91STakashi Iwai };
2647352f7f91STakashi Iwai 
2648352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
2649352f7f91STakashi Iwai {
2650352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2651352f7f91STakashi Iwai 
265212c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
2653352f7f91STakashi Iwai 		return -ENOMEM;
2654352f7f91STakashi Iwai 	return 0;
2655352f7f91STakashi Iwai }
2656352f7f91STakashi Iwai 
2657352f7f91STakashi Iwai /*
2658352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
2659352f7f91STakashi Iwai  * Set up appropriately if really supported
2660352f7f91STakashi Iwai  */
2661352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
2662352f7f91STakashi Iwai {
2663352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2664352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2665352f7f91STakashi Iwai 	int present = 0;
2666352f7f91STakashi Iwai 	int i, err;
2667352f7f91STakashi Iwai 
2668352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
2669352f7f91STakashi Iwai 		present++;
2670352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
2671352f7f91STakashi Iwai 		present++;
2672352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
2673352f7f91STakashi Iwai 		present++;
2674352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
2675352f7f91STakashi Iwai 		return 0;
2676352f7f91STakashi Iwai 
2677352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
2678352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2679352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2680352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2681352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2682352f7f91STakashi Iwai 	}
2683352f7f91STakashi Iwai 
2684352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
2685352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2686352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
2687352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
2688352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
2689352f7f91STakashi Iwai 	}
2690352f7f91STakashi Iwai 
2691352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
2692352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
2693352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
2694352f7f91STakashi Iwai 			continue;
2695352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
2696352f7f91STakashi Iwai 			    nid);
2697352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
26985d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
2699352f7f91STakashi Iwai 		spec->detect_hp = 1;
2700352f7f91STakashi Iwai 	}
2701352f7f91STakashi Iwai 
2702352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
2703352f7f91STakashi Iwai 		if (cfg->speaker_outs)
2704352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
2705352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
2706352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
2707352f7f91STakashi Iwai 					continue;
2708352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
2709352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
2710352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
27115d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
2712352f7f91STakashi Iwai 				spec->detect_lo = 1;
2713352f7f91STakashi Iwai 			}
2714352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
2715352f7f91STakashi Iwai 	}
2716352f7f91STakashi Iwai 
2717352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
2718352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
2719352f7f91STakashi Iwai 
2720352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
2721352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
2722352f7f91STakashi Iwai 
2723352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
2724352f7f91STakashi Iwai 		/* create a control for automute mode */
2725352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
2726352f7f91STakashi Iwai 		if (err < 0)
2727352f7f91STakashi Iwai 			return err;
2728352f7f91STakashi Iwai 	}
2729352f7f91STakashi Iwai 	return 0;
2730352f7f91STakashi Iwai }
2731352f7f91STakashi Iwai 
2732352f7f91STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2733352f7f91STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2734352f7f91STakashi Iwai {
2735352f7f91STakashi Iwai 	int i;
2736352f7f91STakashi Iwai 	for (i = 0; i < nums; i++)
2737352f7f91STakashi Iwai 		if (list[i] == nid)
2738352f7f91STakashi Iwai 			return i;
2739352f7f91STakashi Iwai 	return -1;
2740352f7f91STakashi Iwai }
2741352f7f91STakashi Iwai 
2742352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
2743352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
2744352f7f91STakashi Iwai {
2745352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2746352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2747352f7f91STakashi Iwai 	int i;
2748352f7f91STakashi Iwai 
2749352f7f91STakashi Iwai 	imux = &spec->input_mux;
2750352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
2751352f7f91STakashi Iwai 		spec->am_entry[i].idx =
2752352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
2753352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
2754352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
2755352f7f91STakashi Iwai 			return false; /* no corresponding imux */
2756352f7f91STakashi Iwai 	}
2757352f7f91STakashi Iwai 
2758352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
2759352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
2760352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
2761352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
2762352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
27635d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
2764352f7f91STakashi Iwai 	return true;
2765352f7f91STakashi Iwai }
2766352f7f91STakashi Iwai 
2767352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
2768352f7f91STakashi Iwai {
2769352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
2770352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
2771352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
2772352f7f91STakashi Iwai }
2773352f7f91STakashi Iwai 
2774352f7f91STakashi Iwai /*
2775352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
2776352f7f91STakashi Iwai  * Set up if really supported
2777352f7f91STakashi Iwai  */
2778352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
2779352f7f91STakashi Iwai {
2780352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2781352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2782352f7f91STakashi Iwai 	unsigned int types;
2783352f7f91STakashi Iwai 	int i, num_pins;
2784352f7f91STakashi Iwai 
2785352f7f91STakashi Iwai 	types = 0;
2786352f7f91STakashi Iwai 	num_pins = 0;
2787352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2788352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
2789352f7f91STakashi Iwai 		unsigned int attr;
2790352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
2791352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
2792352f7f91STakashi Iwai 		if (types & (1 << attr))
2793352f7f91STakashi Iwai 			return 0; /* already occupied */
2794352f7f91STakashi Iwai 		switch (attr) {
2795352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
2796352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
2797352f7f91STakashi Iwai 				return 0; /* invalid type */
2798352f7f91STakashi Iwai 			break;
2799352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
2800352f7f91STakashi Iwai 			return 0; /* invalid entry */
2801352f7f91STakashi Iwai 		default:
2802352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
2803352f7f91STakashi Iwai 				return 0; /* invalid type */
2804352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
2805352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
2806352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
2807352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
2808352f7f91STakashi Iwai 				return 0; /* no unsol support */
2809352f7f91STakashi Iwai 			break;
2810352f7f91STakashi Iwai 		}
2811352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
2812352f7f91STakashi Iwai 			return 0;
2813352f7f91STakashi Iwai 		types |= (1 << attr);
2814352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
2815352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
2816352f7f91STakashi Iwai 		num_pins++;
2817352f7f91STakashi Iwai 	}
2818352f7f91STakashi Iwai 
2819352f7f91STakashi Iwai 	if (num_pins < 2)
2820352f7f91STakashi Iwai 		return 0;
2821352f7f91STakashi Iwai 
2822352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
2823352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
2824352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
2825352f7f91STakashi Iwai 	 */
2826352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
2827352f7f91STakashi Iwai 	     compare_attr, NULL);
2828352f7f91STakashi Iwai 
2829352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
2830352f7f91STakashi Iwai 		return 0;
2831352f7f91STakashi Iwai 
2832352f7f91STakashi Iwai 	spec->auto_mic = 1;
2833352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
2834352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
2835352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
2836352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
2837352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
2838352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
2839352f7f91STakashi Iwai 
2840352f7f91STakashi Iwai 	return 0;
2841352f7f91STakashi Iwai }
2842352f7f91STakashi Iwai 
2843352f7f91STakashi Iwai 
28449eb413e5STakashi Iwai /*
28459eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
28469eb413e5STakashi Iwai  *
28479eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
2848352f7f91STakashi Iwai  * or a negative error code
2849352f7f91STakashi Iwai  */
2850352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
28519eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
2852352f7f91STakashi Iwai {
2853352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2854352f7f91STakashi Iwai 	int err;
2855352f7f91STakashi Iwai 
28569eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
28579eb413e5STakashi Iwai 		spec->autocfg = *cfg;
28589eb413e5STakashi Iwai 		cfg = &spec->autocfg;
28599eb413e5STakashi Iwai 	}
28609eb413e5STakashi Iwai 
2861352f7f91STakashi Iwai 	if (!cfg->line_outs) {
2862352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
2863352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
2864352f7f91STakashi Iwai 			spec->no_analog = 1;
2865352f7f91STakashi Iwai 			goto dig_only;
2866352f7f91STakashi Iwai 		}
2867352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
2868352f7f91STakashi Iwai 	}
2869352f7f91STakashi Iwai 
2870352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
2871352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
2872352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
2873352f7f91STakashi Iwai 		/* use HP as primary out */
2874352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2875352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2876352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2877352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
2878352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
2879352f7f91STakashi Iwai 		cfg->hp_outs = 0;
2880352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2881352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
2882352f7f91STakashi Iwai 	}
2883352f7f91STakashi Iwai 
2884352f7f91STakashi Iwai 	err = parse_output_paths(codec);
2885352f7f91STakashi Iwai 	if (err < 0)
2886352f7f91STakashi Iwai 		return err;
2887352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
2888352f7f91STakashi Iwai 	if (err < 0)
2889352f7f91STakashi Iwai 		return err;
2890352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
2891352f7f91STakashi Iwai 	if (err < 0)
2892352f7f91STakashi Iwai 		return err;
2893352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
2894352f7f91STakashi Iwai 	if (err < 0)
2895352f7f91STakashi Iwai 		return err;
2896352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
2897352f7f91STakashi Iwai 	if (err < 0)
2898352f7f91STakashi Iwai 		return err;
2899352f7f91STakashi Iwai 	err = create_shared_input(codec);
2900352f7f91STakashi Iwai 	if (err < 0)
2901352f7f91STakashi Iwai 		return err;
2902352f7f91STakashi Iwai 	err = create_input_ctls(codec);
2903352f7f91STakashi Iwai 	if (err < 0)
2904352f7f91STakashi Iwai 		return err;
2905352f7f91STakashi Iwai 
2906352f7f91STakashi Iwai 	/* check the multiple speaker pins */
2907352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2908352f7f91STakashi Iwai 		spec->const_channel_count = cfg->line_outs * 2;
2909352f7f91STakashi Iwai 	else
2910352f7f91STakashi Iwai 		spec->const_channel_count = cfg->speaker_outs * 2;
2911352f7f91STakashi Iwai 
2912352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
2913352f7f91STakashi Iwai 		spec->multiout.max_channels = max(spec->ext_channel_count,
2914352f7f91STakashi Iwai 						  spec->const_channel_count);
2915352f7f91STakashi Iwai 	else
2916352f7f91STakashi Iwai 		spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2917352f7f91STakashi Iwai 
2918352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
2919352f7f91STakashi Iwai 	if (err < 0)
2920352f7f91STakashi Iwai 		return err;
2921352f7f91STakashi Iwai 
2922352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
2923352f7f91STakashi Iwai 	if (err < 0)
2924352f7f91STakashi Iwai 		return err;
2925352f7f91STakashi Iwai 
2926352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
2927352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
2928352f7f91STakashi Iwai 		if (err < 0)
2929352f7f91STakashi Iwai 			return err;
2930352f7f91STakashi Iwai 	}
2931352f7f91STakashi Iwai 
2932352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
2933352f7f91STakashi Iwai 	if (err < 0)
2934352f7f91STakashi Iwai 		return err;
2935352f7f91STakashi Iwai 
2936352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
2937352f7f91STakashi Iwai 	if (err < 0)
2938352f7f91STakashi Iwai 		return err;
2939352f7f91STakashi Iwai 
2940352f7f91STakashi Iwai  dig_only:
2941352f7f91STakashi Iwai 	parse_digital(codec);
2942352f7f91STakashi Iwai 
2943352f7f91STakashi Iwai 	return 1;
2944352f7f91STakashi Iwai }
2945352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
2946352f7f91STakashi Iwai 
2947352f7f91STakashi Iwai 
2948352f7f91STakashi Iwai /*
2949352f7f91STakashi Iwai  * Build control elements
2950352f7f91STakashi Iwai  */
2951352f7f91STakashi Iwai 
2952352f7f91STakashi Iwai /* slave controls for virtual master */
2953352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
2954352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
2955352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
2956352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
2957352f7f91STakashi Iwai 	NULL,
2958352f7f91STakashi Iwai };
2959352f7f91STakashi Iwai 
2960352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
2961352f7f91STakashi Iwai {
2962352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2963352f7f91STakashi Iwai 	int err;
2964352f7f91STakashi Iwai 
296536502d02STakashi Iwai 	if (spec->kctls.used) {
2966352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
2967352f7f91STakashi Iwai 		if (err < 0)
2968352f7f91STakashi Iwai 			return err;
296936502d02STakashi Iwai 	}
2970352f7f91STakashi Iwai 
2971352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
2972352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
2973352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
2974352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
2975352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
2976352f7f91STakashi Iwai 		if (err < 0)
2977352f7f91STakashi Iwai 			return err;
2978352f7f91STakashi Iwai 		if (!spec->no_analog) {
2979352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
2980352f7f91STakashi Iwai 							    &spec->multiout);
2981352f7f91STakashi Iwai 			if (err < 0)
2982352f7f91STakashi Iwai 				return err;
2983352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
2984352f7f91STakashi Iwai 		}
2985352f7f91STakashi Iwai 	}
2986352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
2987352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
2988352f7f91STakashi Iwai 		if (err < 0)
2989352f7f91STakashi Iwai 			return err;
2990352f7f91STakashi Iwai 	}
2991352f7f91STakashi Iwai 
2992352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
2993352f7f91STakashi Iwai 	if (!spec->no_analog &&
2994352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
2995352f7f91STakashi Iwai 		unsigned int vmaster_tlv[4];
2996352f7f91STakashi Iwai 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
2997352f7f91STakashi Iwai 					HDA_OUTPUT, vmaster_tlv);
2998352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
2999352f7f91STakashi Iwai 					  vmaster_tlv, slave_pfxs,
3000352f7f91STakashi Iwai 					  "Playback Volume");
3001352f7f91STakashi Iwai 		if (err < 0)
3002352f7f91STakashi Iwai 			return err;
3003352f7f91STakashi Iwai 	}
3004352f7f91STakashi Iwai 	if (!spec->no_analog &&
3005352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3006352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3007352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3008352f7f91STakashi Iwai 					    "Playback Switch",
3009352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3010352f7f91STakashi Iwai 		if (err < 0)
3011352f7f91STakashi Iwai 			return err;
3012352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3013fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3014fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3015352f7f91STakashi Iwai 	}
3016352f7f91STakashi Iwai 
3017352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3018352f7f91STakashi Iwai 
3019352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3020352f7f91STakashi Iwai 		int err;
3021352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3022352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3023352f7f91STakashi Iwai 		if (err < 0)
3024352f7f91STakashi Iwai 			return err;
3025352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3026352f7f91STakashi Iwai 		if (err < 0)
3027352f7f91STakashi Iwai 			return err;
3028352f7f91STakashi Iwai 	}
3029352f7f91STakashi Iwai 
3030352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3031352f7f91STakashi Iwai 	if (err < 0)
3032352f7f91STakashi Iwai 		return err;
3033352f7f91STakashi Iwai 
3034352f7f91STakashi Iwai 	return 0;
3035352f7f91STakashi Iwai }
3036352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3037352f7f91STakashi Iwai 
3038352f7f91STakashi Iwai 
3039352f7f91STakashi Iwai /*
3040352f7f91STakashi Iwai  * PCM definitions
3041352f7f91STakashi Iwai  */
3042352f7f91STakashi Iwai 
3043352f7f91STakashi Iwai /*
3044352f7f91STakashi Iwai  * Analog playback callbacks
3045352f7f91STakashi Iwai  */
3046352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3047352f7f91STakashi Iwai 			     struct hda_codec *codec,
3048352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3049352f7f91STakashi Iwai {
3050352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3051352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
3052352f7f91STakashi Iwai 					     hinfo);
3053352f7f91STakashi Iwai }
3054352f7f91STakashi Iwai 
3055352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
305697ec558aSTakashi Iwai 				struct hda_codec *codec,
305797ec558aSTakashi Iwai 				unsigned int stream_tag,
305897ec558aSTakashi Iwai 				unsigned int format,
305997ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
306097ec558aSTakashi Iwai {
3061352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3062352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3063352f7f91STakashi Iwai 						stream_tag, format, substream);
3064352f7f91STakashi Iwai }
306597ec558aSTakashi Iwai 
3066352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3067352f7f91STakashi Iwai 				struct hda_codec *codec,
3068352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3069352f7f91STakashi Iwai {
3070352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3071352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3072352f7f91STakashi Iwai }
3073352f7f91STakashi Iwai 
3074352f7f91STakashi Iwai /*
3075352f7f91STakashi Iwai  * Digital out
3076352f7f91STakashi Iwai  */
3077352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3078352f7f91STakashi Iwai 				 struct hda_codec *codec,
3079352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
3080352f7f91STakashi Iwai {
3081352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3082352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3083352f7f91STakashi Iwai }
3084352f7f91STakashi Iwai 
3085352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3086352f7f91STakashi Iwai 				    struct hda_codec *codec,
3087352f7f91STakashi Iwai 				    unsigned int stream_tag,
3088352f7f91STakashi Iwai 				    unsigned int format,
3089352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3090352f7f91STakashi Iwai {
3091352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3092352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3093352f7f91STakashi Iwai 					     stream_tag, format, substream);
3094352f7f91STakashi Iwai }
3095352f7f91STakashi Iwai 
3096352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3097352f7f91STakashi Iwai 				    struct hda_codec *codec,
3098352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3099352f7f91STakashi Iwai {
3100352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3101352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3102352f7f91STakashi Iwai }
3103352f7f91STakashi Iwai 
3104352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3105352f7f91STakashi Iwai 				  struct hda_codec *codec,
3106352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
3107352f7f91STakashi Iwai {
3108352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3109352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3110352f7f91STakashi Iwai }
3111352f7f91STakashi Iwai 
3112352f7f91STakashi Iwai /*
3113352f7f91STakashi Iwai  * Analog capture
3114352f7f91STakashi Iwai  */
3115352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3116352f7f91STakashi Iwai 				   struct hda_codec *codec,
3117352f7f91STakashi Iwai 				   unsigned int stream_tag,
3118352f7f91STakashi Iwai 				   unsigned int format,
3119352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
3120352f7f91STakashi Iwai {
3121352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3122352f7f91STakashi Iwai 
3123352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
312497ec558aSTakashi Iwai 				   stream_tag, 0, format);
312597ec558aSTakashi Iwai 	return 0;
312697ec558aSTakashi Iwai }
312797ec558aSTakashi Iwai 
3128352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
312997ec558aSTakashi Iwai 				   struct hda_codec *codec,
313097ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
313197ec558aSTakashi Iwai {
3132352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
313397ec558aSTakashi Iwai 
3134352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
3135352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
313697ec558aSTakashi Iwai 	return 0;
313797ec558aSTakashi Iwai }
313897ec558aSTakashi Iwai 
3139352f7f91STakashi Iwai /*
3140352f7f91STakashi Iwai  */
3141352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
3142352f7f91STakashi Iwai 	.substreams = 1,
3143352f7f91STakashi Iwai 	.channels_min = 2,
3144352f7f91STakashi Iwai 	.channels_max = 8,
3145352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3146352f7f91STakashi Iwai 	.ops = {
3147352f7f91STakashi Iwai 		.open = playback_pcm_open,
3148352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
3149352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
3150352f7f91STakashi Iwai 	},
3151352f7f91STakashi Iwai };
3152352f7f91STakashi Iwai 
3153352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
3154352f7f91STakashi Iwai 	.substreams = 1,
3155352f7f91STakashi Iwai 	.channels_min = 2,
3156352f7f91STakashi Iwai 	.channels_max = 2,
3157352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3158352f7f91STakashi Iwai };
3159352f7f91STakashi Iwai 
3160352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
3161352f7f91STakashi Iwai 	.substreams = 1,
3162352f7f91STakashi Iwai 	.channels_min = 2,
3163352f7f91STakashi Iwai 	.channels_max = 2,
3164352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3165352f7f91STakashi Iwai };
3166352f7f91STakashi Iwai 
3167352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
3168352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
3169352f7f91STakashi Iwai 	.channels_min = 2,
3170352f7f91STakashi Iwai 	.channels_max = 2,
3171352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3172352f7f91STakashi Iwai 	.ops = {
3173352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
3174352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
3175352f7f91STakashi Iwai 	},
3176352f7f91STakashi Iwai };
3177352f7f91STakashi Iwai 
3178352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
3179352f7f91STakashi Iwai 	.substreams = 1,
3180352f7f91STakashi Iwai 	.channels_min = 2,
3181352f7f91STakashi Iwai 	.channels_max = 2,
3182352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3183352f7f91STakashi Iwai 	.ops = {
3184352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
3185352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
3186352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
3187352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
3188352f7f91STakashi Iwai 	},
3189352f7f91STakashi Iwai };
3190352f7f91STakashi Iwai 
3191352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
3192352f7f91STakashi Iwai 	.substreams = 1,
3193352f7f91STakashi Iwai 	.channels_min = 2,
3194352f7f91STakashi Iwai 	.channels_max = 2,
3195352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3196352f7f91STakashi Iwai };
3197352f7f91STakashi Iwai 
3198352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
3199352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
3200352f7f91STakashi Iwai 	.substreams = 0,
3201352f7f91STakashi Iwai 	.channels_min = 0,
3202352f7f91STakashi Iwai 	.channels_max = 0,
3203352f7f91STakashi Iwai };
3204352f7f91STakashi Iwai 
3205352f7f91STakashi Iwai /*
3206352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
3207352f7f91STakashi Iwai  */
3208352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
32091da177e4SLinus Torvalds {
3210352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3211352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
32121da177e4SLinus Torvalds 
3213352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
3214352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
3215352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3216352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
3217352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
3218352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
3219352f7f91STakashi Iwai 					   spec->cur_adc_format);
3220352f7f91STakashi Iwai 		return true;
3221352f7f91STakashi Iwai 	}
3222352f7f91STakashi Iwai 	return false;
3223352f7f91STakashi Iwai }
3224352f7f91STakashi Iwai 
3225352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
3226352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3227352f7f91STakashi Iwai 				       struct hda_codec *codec,
3228352f7f91STakashi Iwai 				       unsigned int stream_tag,
3229352f7f91STakashi Iwai 				       unsigned int format,
3230352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3231352f7f91STakashi Iwai {
3232352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3233352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
3234352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
3235352f7f91STakashi Iwai 	spec->cur_adc_format = format;
3236352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
32371da177e4SLinus Torvalds 	return 0;
32381da177e4SLinus Torvalds }
32391da177e4SLinus Torvalds 
3240352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3241352f7f91STakashi Iwai 				       struct hda_codec *codec,
3242352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3243352f7f91STakashi Iwai {
3244352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3245352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3246352f7f91STakashi Iwai 	spec->cur_adc = 0;
3247352f7f91STakashi Iwai 	return 0;
3248352f7f91STakashi Iwai }
3249352f7f91STakashi Iwai 
3250352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
3251352f7f91STakashi Iwai 	.substreams = 1,
3252352f7f91STakashi Iwai 	.channels_min = 2,
3253352f7f91STakashi Iwai 	.channels_max = 2,
3254352f7f91STakashi Iwai 	.nid = 0, /* fill later */
3255352f7f91STakashi Iwai 	.ops = {
3256352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
3257352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
3258352f7f91STakashi Iwai 	},
3259352f7f91STakashi Iwai };
3260352f7f91STakashi Iwai 
3261f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
3262f873e536STakashi Iwai 				 const char *chip_name)
3263f873e536STakashi Iwai {
3264f873e536STakashi Iwai 	char *p;
3265f873e536STakashi Iwai 
3266f873e536STakashi Iwai 	if (*str)
3267f873e536STakashi Iwai 		return;
3268f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
3269f873e536STakashi Iwai 
3270f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
3271f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
3272f873e536STakashi Iwai 		if (!isalnum(p[1])) {
3273f873e536STakashi Iwai 			*p = 0;
3274f873e536STakashi Iwai 			break;
3275f873e536STakashi Iwai 		}
3276f873e536STakashi Iwai 	}
3277f873e536STakashi Iwai 	strlcat(str, sfx, len);
3278f873e536STakashi Iwai }
3279f873e536STakashi Iwai 
3280352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
3281352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
3282352f7f91STakashi Iwai {
3283352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3284352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
3285352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
3286352f7f91STakashi Iwai 	bool have_multi_adcs;
3287352f7f91STakashi Iwai 
32881da177e4SLinus Torvalds 	codec->num_pcms = 1;
32891da177e4SLinus Torvalds 	codec->pcm_info = info;
32901da177e4SLinus Torvalds 
3291352f7f91STakashi Iwai 	if (spec->no_analog)
3292352f7f91STakashi Iwai 		goto skip_analog;
3293352f7f91STakashi Iwai 
3294f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
3295f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
3296f873e536STakashi Iwai 			     " Analog", codec->chip_name);
3297352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
3298352f7f91STakashi Iwai 
3299352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
3300352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
3301352f7f91STakashi Iwai 		if (!p)
3302352f7f91STakashi Iwai 			p = &pcm_analog_playback;
3303352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3304352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3305352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3306352f7f91STakashi Iwai 			spec->multiout.max_channels;
3307352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
3308352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
3309352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
3310352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
3311352f7f91STakashi Iwai 	}
3312352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
3313352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
3314352f7f91STakashi Iwai 		if (!p) {
3315352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
3316352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
3317352f7f91STakashi Iwai 			else
3318352f7f91STakashi Iwai 				p = &pcm_analog_capture;
3319352f7f91STakashi Iwai 		}
3320352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3321352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3322352f7f91STakashi Iwai 	}
3323352f7f91STakashi Iwai 
3324352f7f91STakashi Iwai  skip_analog:
3325352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
3326352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3327f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
3328352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
3329f873e536STakashi Iwai 				     " Digital", codec->chip_name);
3330352f7f91STakashi Iwai 		codec->num_pcms = 2;
3331352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
3332352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
3333352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
3334352f7f91STakashi Iwai 		if (spec->dig_out_type)
3335352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
3336352f7f91STakashi Iwai 		else
3337352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
3338352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
3339352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
3340352f7f91STakashi Iwai 			if (!p)
3341352f7f91STakashi Iwai 				p = &pcm_digital_playback;
3342352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3343352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3344352f7f91STakashi Iwai 		}
3345352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
3346352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
3347352f7f91STakashi Iwai 			if (!p)
3348352f7f91STakashi Iwai 				p = &pcm_digital_capture;
3349352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3350352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3351352f7f91STakashi Iwai 		}
3352352f7f91STakashi Iwai 	}
3353352f7f91STakashi Iwai 
3354352f7f91STakashi Iwai 	if (spec->no_analog)
3355352f7f91STakashi Iwai 		return 0;
3356352f7f91STakashi Iwai 
3357352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
3358352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
3359352f7f91STakashi Iwai 	 */
3360352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
3361352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
3362352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
3363352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
3364352f7f91STakashi Iwai 		codec->num_pcms = 3;
3365352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
3366352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
3367352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
3368352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
3369352f7f91STakashi Iwai 			if (!p)
3370352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
3371352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3372352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3373352f7f91STakashi Iwai 				spec->alt_dac_nid;
3374352f7f91STakashi Iwai 		} else {
3375352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3376352f7f91STakashi Iwai 				pcm_null_stream;
3377352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3378352f7f91STakashi Iwai 		}
3379352f7f91STakashi Iwai 		if (have_multi_adcs) {
3380352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
3381352f7f91STakashi Iwai 			if (!p)
3382352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
3383352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3384352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3385352f7f91STakashi Iwai 				spec->adc_nids[1];
3386352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3387352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
3388352f7f91STakashi Iwai 		} else {
3389352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3390352f7f91STakashi Iwai 				pcm_null_stream;
3391352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
3392352f7f91STakashi Iwai 		}
33931da177e4SLinus Torvalds 	}
33941da177e4SLinus Torvalds 
33951da177e4SLinus Torvalds 	return 0;
33961da177e4SLinus Torvalds }
3397352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
3398352f7f91STakashi Iwai 
3399352f7f91STakashi Iwai 
3400352f7f91STakashi Iwai /*
3401352f7f91STakashi Iwai  * Standard auto-parser initializations
3402352f7f91STakashi Iwai  */
3403352f7f91STakashi Iwai 
3404352f7f91STakashi Iwai /* configure the path from the given dac to the pin as the proper output */
3405352f7f91STakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, hda_nid_t pin,
3406352f7f91STakashi Iwai 				  int pin_type, hda_nid_t dac)
3407352f7f91STakashi Iwai {
3408352f7f91STakashi Iwai 	struct nid_path *path;
3409352f7f91STakashi Iwai 
3410352f7f91STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, pin_type);
3411352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, dac, pin);
3412352f7f91STakashi Iwai 	if (!path)
3413352f7f91STakashi Iwai 		return;
3414352f7f91STakashi Iwai 	if (path->active)
3415352f7f91STakashi Iwai 		return;
3416352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, true);
3417d5a9f1bbSTakashi Iwai 	set_pin_eapd(codec, pin, true);
3418352f7f91STakashi Iwai }
3419352f7f91STakashi Iwai 
3420352f7f91STakashi Iwai /* initialize primary output paths */
3421352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
3422352f7f91STakashi Iwai {
3423352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
342464049c81STakashi Iwai 	hda_nid_t nid, dac;
3425352f7f91STakashi Iwai 	int pin_type;
3426352f7f91STakashi Iwai 	int i;
3427352f7f91STakashi Iwai 
3428352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3429352f7f91STakashi Iwai 		pin_type = PIN_HP;
3430352f7f91STakashi Iwai 	else
3431352f7f91STakashi Iwai 		pin_type = PIN_OUT;
3432352f7f91STakashi Iwai 
343364049c81STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++) {
343464049c81STakashi Iwai 		nid = spec->autocfg.line_out_pins[i];
343564049c81STakashi Iwai 		if (nid) {
343664049c81STakashi Iwai 			dac = spec->multiout.dac_nids[i];
343764049c81STakashi Iwai 			if (!dac)
343864049c81STakashi Iwai 				dac = spec->multiout.dac_nids[0];
343964049c81STakashi Iwai 			set_output_and_unmute(codec, nid, pin_type, dac);
344064049c81STakashi Iwai 		}
3441352f7f91STakashi Iwai 	}
3442352f7f91STakashi Iwai }
3443352f7f91STakashi Iwai 
3444db23fd19STakashi Iwai 
3445db23fd19STakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs,
3446db23fd19STakashi Iwai 			     hda_nid_t *pins, hda_nid_t *dacs, int type)
3447352f7f91STakashi Iwai {
3448352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3449352f7f91STakashi Iwai 	int i;
3450352f7f91STakashi Iwai 	hda_nid_t pin, dac;
3451352f7f91STakashi Iwai 
3452db23fd19STakashi Iwai 	for (i = 0; i < num_outs; i++) {
3453db23fd19STakashi Iwai 		pin = pins[i];
3454352f7f91STakashi Iwai 		if (!pin)
3455352f7f91STakashi Iwai 			break;
3456db23fd19STakashi Iwai 		dac = dacs[i];
3457352f7f91STakashi Iwai 		if (!dac) {
3458db23fd19STakashi Iwai 			if (i > 0 && dacs[0])
3459db23fd19STakashi Iwai 				dac = dacs[0];
3460352f7f91STakashi Iwai 			else
3461352f7f91STakashi Iwai 				dac = spec->multiout.dac_nids[0];
3462352f7f91STakashi Iwai 		}
3463db23fd19STakashi Iwai 		set_output_and_unmute(codec, pin, type, dac);
3464352f7f91STakashi Iwai 	}
3465352f7f91STakashi Iwai }
3466db23fd19STakashi Iwai 
3467db23fd19STakashi Iwai /* initialize hp and speaker paths */
3468db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
3469db23fd19STakashi Iwai {
3470db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3471db23fd19STakashi Iwai 
3472db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
3473db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs,
3474db23fd19STakashi Iwai 				 spec->autocfg.hp_pins,
3475db23fd19STakashi Iwai 				 spec->multiout.hp_out_nid, PIN_HP);
3476db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
3477db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
3478db23fd19STakashi Iwai 				 spec->autocfg.speaker_pins,
3479db23fd19STakashi Iwai 				 spec->multiout.extra_out_nid, PIN_OUT);
3480352f7f91STakashi Iwai }
3481352f7f91STakashi Iwai 
3482352f7f91STakashi Iwai /* initialize multi-io paths */
3483352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
3484352f7f91STakashi Iwai {
3485352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3486352f7f91STakashi Iwai 	int i;
3487352f7f91STakashi Iwai 
3488352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
3489352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
3490352f7f91STakashi Iwai 		struct nid_path *path;
3491352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->multi_io[i].dac, pin);
3492352f7f91STakashi Iwai 		if (!path)
3493352f7f91STakashi Iwai 			continue;
3494352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
3495352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
3496352f7f91STakashi Iwai 				snd_hda_codec_update_cache(codec, pin, 0,
3497352f7f91STakashi Iwai 					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3498352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
3499352f7f91STakashi Iwai 	}
3500352f7f91STakashi Iwai }
3501352f7f91STakashi Iwai 
3502352f7f91STakashi Iwai /* set up the input pin config, depending on the given auto-pin type */
3503352f7f91STakashi Iwai static void set_input_pin(struct hda_codec *codec, hda_nid_t nid,
3504352f7f91STakashi Iwai 			  int auto_pin_type)
3505352f7f91STakashi Iwai {
3506352f7f91STakashi Iwai 	unsigned int val = PIN_IN;
3507352f7f91STakashi Iwai 	if (auto_pin_type == AUTO_PIN_MIC)
3508352f7f91STakashi Iwai 		val |= snd_hda_get_default_vref(codec, nid);
35097594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
3510352f7f91STakashi Iwai }
3511352f7f91STakashi Iwai 
3512352f7f91STakashi Iwai /* set up input pins and loopback paths */
3513352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
3514352f7f91STakashi Iwai {
3515352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3516352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3517352f7f91STakashi Iwai 	int i;
3518352f7f91STakashi Iwai 
3519352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3520352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3521352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
3522352f7f91STakashi Iwai 			set_input_pin(codec, nid, cfg->inputs[i].type);
3523352f7f91STakashi Iwai 
3524352f7f91STakashi Iwai 		/* init loopback inputs */
3525352f7f91STakashi Iwai 		if (spec->mixer_nid) {
3526352f7f91STakashi Iwai 			struct nid_path *path;
3527352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, spec->mixer_nid);
3528352f7f91STakashi Iwai 			if (path)
3529352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
3530352f7f91STakashi Iwai 						      path->active, false);
3531352f7f91STakashi Iwai 		}
3532352f7f91STakashi Iwai 	}
3533352f7f91STakashi Iwai }
3534352f7f91STakashi Iwai 
3535352f7f91STakashi Iwai /* initialize ADC paths */
3536352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
3537352f7f91STakashi Iwai {
3538352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3539352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3540352f7f91STakashi Iwai 	struct nid_path *path;
3541352f7f91STakashi Iwai 	int i, c, nums;
3542352f7f91STakashi Iwai 
3543352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3544352f7f91STakashi Iwai 		nums = 1;
3545352f7f91STakashi Iwai 	else
3546352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3547352f7f91STakashi Iwai 
3548352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
3549352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3550352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
3551352f7f91STakashi Iwai 						    get_adc_nid(codec, c, i));
3552352f7f91STakashi Iwai 			if (path) {
3553352f7f91STakashi Iwai 				bool active = path->active;
3554352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
3555352f7f91STakashi Iwai 					active = true;
3556352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
3557352f7f91STakashi Iwai 			}
3558352f7f91STakashi Iwai 		}
3559352f7f91STakashi Iwai 	}
3560352f7f91STakashi Iwai 
3561352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3562352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
3563352f7f91STakashi Iwai 
3564352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3565352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
3566352f7f91STakashi Iwai }
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai /* set right pin controls for digital I/O */
3569352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
3570352f7f91STakashi Iwai {
3571352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3572352f7f91STakashi Iwai 	int i;
3573352f7f91STakashi Iwai 	hda_nid_t pin;
3574352f7f91STakashi Iwai 
3575352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
3576352f7f91STakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3577352f7f91STakashi Iwai 		if (!pin)
3578352f7f91STakashi Iwai 			continue;
3579352f7f91STakashi Iwai 		set_output_and_unmute(codec, pin, PIN_OUT, 0);
3580352f7f91STakashi Iwai 	}
3581352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
3582352f7f91STakashi Iwai 	if (pin)
35837594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, pin, PIN_IN);
3584352f7f91STakashi Iwai }
3585352f7f91STakashi Iwai 
3586973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
3587973e4972STakashi Iwai  * invalid unsol tags by some reason
3588973e4972STakashi Iwai  */
3589973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
3590973e4972STakashi Iwai {
3591973e4972STakashi Iwai 	int i;
3592973e4972STakashi Iwai 
3593973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
3594973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
3595973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
3596973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
3597973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
3598973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
3599973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
3600973e4972STakashi Iwai 	}
3601973e4972STakashi Iwai }
3602973e4972STakashi Iwai 
3603352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
3604352f7f91STakashi Iwai {
3605352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3606352f7f91STakashi Iwai 
3607352f7f91STakashi Iwai 	if (spec->init_hook)
3608352f7f91STakashi Iwai 		spec->init_hook(codec);
3609352f7f91STakashi Iwai 
3610352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
3611352f7f91STakashi Iwai 
36123bbcd274STakashi Iwai 	codec->cached_write = 1;
36133bbcd274STakashi Iwai 
3614352f7f91STakashi Iwai 	init_multi_out(codec);
3615352f7f91STakashi Iwai 	init_extra_out(codec);
3616352f7f91STakashi Iwai 	init_multi_io(codec);
3617352f7f91STakashi Iwai 	init_analog_input(codec);
3618352f7f91STakashi Iwai 	init_input_src(codec);
3619352f7f91STakashi Iwai 	init_digital(codec);
3620352f7f91STakashi Iwai 
3621973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
3622973e4972STakashi Iwai 
3623352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
36245d550e15STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
36255d550e15STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
36265d550e15STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
3627352f7f91STakashi Iwai 
36283bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
36293bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
36303bbcd274STakashi Iwai 
3631352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
3632352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
3633352f7f91STakashi Iwai 
3634352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
3635352f7f91STakashi Iwai 	return 0;
3636352f7f91STakashi Iwai }
3637352f7f91STakashi Iwai EXPORT_SYMBOL(snd_hda_gen_init);
3638352f7f91STakashi Iwai 
3639352f7f91STakashi Iwai 
3640352f7f91STakashi Iwai /*
3641352f7f91STakashi Iwai  * the generic codec support
3642352f7f91STakashi Iwai  */
36431da177e4SLinus Torvalds 
364483012a7cSTakashi Iwai #ifdef CONFIG_PM
3645cb53c626STakashi Iwai static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3646cb53c626STakashi Iwai {
3647352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3648cb53c626STakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3649cb53c626STakashi Iwai }
3650cb53c626STakashi Iwai #endif
3651cb53c626STakashi Iwai 
3652352f7f91STakashi Iwai static void generic_free(struct hda_codec *codec)
3653352f7f91STakashi Iwai {
3654352f7f91STakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
3655352f7f91STakashi Iwai 	kfree(codec->spec);
3656352f7f91STakashi Iwai 	codec->spec = NULL;
3657352f7f91STakashi Iwai }
36581da177e4SLinus Torvalds 
3659352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
3660352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
3661352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
3662352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
3663352f7f91STakashi Iwai 	.free = generic_free,
3664352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
366583012a7cSTakashi Iwai #ifdef CONFIG_PM
3666cb53c626STakashi Iwai 	.check_power_status = generic_check_power_status,
3667cb53c626STakashi Iwai #endif
36681da177e4SLinus Torvalds };
36691da177e4SLinus Torvalds 
36701da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
36711da177e4SLinus Torvalds {
3672352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
36731da177e4SLinus Torvalds 	int err;
36741da177e4SLinus Torvalds 
3675e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3676352f7f91STakashi Iwai 	if (!spec)
36771da177e4SLinus Torvalds 		return -ENOMEM;
3678352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
36791da177e4SLinus Torvalds 	codec->spec = spec;
36801da177e4SLinus Torvalds 
36819eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
36829eb413e5STakashi Iwai 	if (err < 0)
36839eb413e5STakashi Iwai 		return err;
36849eb413e5STakashi Iwai 
36859eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
3686352f7f91STakashi Iwai 	if (err < 0)
36871da177e4SLinus Torvalds 		goto error;
36881da177e4SLinus Torvalds 
36891da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
36901da177e4SLinus Torvalds 	return 0;
36911da177e4SLinus Torvalds 
36921da177e4SLinus Torvalds error:
3693352f7f91STakashi Iwai 	generic_free(codec);
36941da177e4SLinus Torvalds 	return err;
36951da177e4SLinus Torvalds }
36961289e9e8STakashi Iwai EXPORT_SYMBOL(snd_hda_parse_generic_codec);
3697