xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision ee79c69a)
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);
4438cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
45352f7f91STakashi Iwai 	return 0;
46352f7f91STakashi Iwai }
47352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
481da177e4SLinus Torvalds 
4912c93df6STakashi Iwai struct snd_kcontrol_new *
5012c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
51352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
52352f7f91STakashi Iwai {
53352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
54352f7f91STakashi Iwai 	if (!knew)
55352f7f91STakashi Iwai 		return NULL;
56352f7f91STakashi Iwai 	*knew = *temp;
57352f7f91STakashi Iwai 	if (name)
58352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
59352f7f91STakashi Iwai 	else if (knew->name)
60352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
61352f7f91STakashi Iwai 	if (!knew->name)
62352f7f91STakashi Iwai 		return NULL;
63352f7f91STakashi Iwai 	return knew;
64352f7f91STakashi Iwai }
6512c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
66352f7f91STakashi Iwai 
67352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
68352f7f91STakashi Iwai {
69352f7f91STakashi Iwai 	if (spec->kctls.list) {
70352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
71352f7f91STakashi Iwai 		int i;
72352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
73352f7f91STakashi Iwai 			kfree(kctl[i].name);
74352f7f91STakashi Iwai 	}
75352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
76352f7f91STakashi Iwai }
77352f7f91STakashi Iwai 
78352f7f91STakashi Iwai static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
79352f7f91STakashi Iwai 					  unsigned int nums,
80352f7f91STakashi Iwai 					  struct hda_ctl_ops *ops)
81352f7f91STakashi Iwai {
82352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
83352f7f91STakashi Iwai 	struct hda_bind_ctls **ctlp, *ctl;
84352f7f91STakashi Iwai 	ctlp = snd_array_new(&spec->bind_ctls);
85352f7f91STakashi Iwai 	if (!ctlp)
86352f7f91STakashi Iwai 		return NULL;
87352f7f91STakashi Iwai 	ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
88352f7f91STakashi Iwai 	*ctlp = ctl;
89352f7f91STakashi Iwai 	if (ctl)
90352f7f91STakashi Iwai 		ctl->ops = ops;
91352f7f91STakashi Iwai 	return ctl;
92352f7f91STakashi Iwai }
93352f7f91STakashi Iwai 
94352f7f91STakashi Iwai static void free_bind_ctls(struct hda_gen_spec *spec)
95352f7f91STakashi Iwai {
96352f7f91STakashi Iwai 	if (spec->bind_ctls.list) {
97352f7f91STakashi Iwai 		struct hda_bind_ctls **ctl = spec->bind_ctls.list;
98352f7f91STakashi Iwai 		int i;
99352f7f91STakashi Iwai 		for (i = 0; i < spec->bind_ctls.used; i++)
100352f7f91STakashi Iwai 			kfree(ctl[i]);
101352f7f91STakashi Iwai 	}
102352f7f91STakashi Iwai 	snd_array_free(&spec->bind_ctls);
103352f7f91STakashi Iwai }
104352f7f91STakashi Iwai 
105352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
106352f7f91STakashi Iwai {
1071da177e4SLinus Torvalds 	if (!spec)
1081da177e4SLinus Torvalds 		return;
109352f7f91STakashi Iwai 	free_kctls(spec);
110352f7f91STakashi Iwai 	free_bind_ctls(spec);
111352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1121da177e4SLinus Torvalds }
113352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds /*
116352f7f91STakashi Iwai  * parsing paths
1171da177e4SLinus Torvalds  */
1181da177e4SLinus Torvalds 
119f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
120f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
121f5172a7eSTakashi Iwai 				     int with_aa_mix)
1221da177e4SLinus Torvalds {
123352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
124352f7f91STakashi Iwai 	int i;
1251da177e4SLinus Torvalds 
126352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
127352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
128352f7f91STakashi Iwai 		if (path->depth <= 0)
129352f7f91STakashi Iwai 			continue;
130352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
131f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
132f5172a7eSTakashi Iwai 			if (with_aa_mix == HDA_PARSE_ALL ||
133f5172a7eSTakashi Iwai 			    path->with_aa_mix == with_aa_mix)
134352f7f91STakashi Iwai 				return path;
1351da177e4SLinus Torvalds 		}
136f5172a7eSTakashi Iwai 	}
1371da177e4SLinus Torvalds 	return NULL;
1381da177e4SLinus Torvalds }
139f5172a7eSTakashi Iwai 
140f5172a7eSTakashi Iwai /* get the path between the given NIDs;
141f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
142f5172a7eSTakashi Iwai  */
143f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
144f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
145f5172a7eSTakashi Iwai {
146f5172a7eSTakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, HDA_PARSE_ALL);
147f5172a7eSTakashi Iwai }
148352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
1491da177e4SLinus Torvalds 
150196c1766STakashi Iwai /* get the index number corresponding to the path instance;
151196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
152196c1766STakashi Iwai  */
153196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
154196c1766STakashi Iwai {
155196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
156196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
157196c1766STakashi Iwai 	ssize_t idx;
158196c1766STakashi Iwai 
159196c1766STakashi Iwai 	if (!spec->paths.used)
160196c1766STakashi Iwai 		return 0;
161196c1766STakashi Iwai 	idx = path - array;
162196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
163196c1766STakashi Iwai 		return 0;
164196c1766STakashi Iwai 	return idx + 1;
165196c1766STakashi Iwai }
166196c1766STakashi Iwai 
167196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
168196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
169196c1766STakashi Iwai {
170196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
171196c1766STakashi Iwai 
172196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
173196c1766STakashi Iwai 		return NULL;
174196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
175196c1766STakashi Iwai }
176196c1766STakashi Iwai 
177352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
178352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
1791da177e4SLinus Torvalds {
180352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
181352f7f91STakashi Iwai 	int i;
182352f7f91STakashi Iwai 
183352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
184352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
185352f7f91STakashi Iwai 		if (path->path[0] == nid)
186352f7f91STakashi Iwai 			return true;
187352f7f91STakashi Iwai 	}
188352f7f91STakashi Iwai 	return false;
1891da177e4SLinus Torvalds }
1901da177e4SLinus Torvalds 
191352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
192352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
193352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
1941da177e4SLinus Torvalds {
195352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
196352f7f91STakashi Iwai 		return false;
197352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
1981da177e4SLinus Torvalds }
1991da177e4SLinus Torvalds 
200352f7f91STakashi Iwai /* nid, dir and idx */
201352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
202352f7f91STakashi Iwai 
203352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
204352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
2051da177e4SLinus Torvalds {
206352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
207352f7f91STakashi Iwai 	int i;
208352f7f91STakashi Iwai 
209352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
210352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
211352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
212352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
213352f7f91STakashi Iwai 			return true;
214352f7f91STakashi Iwai 	}
215352f7f91STakashi Iwai 	return false;
2161da177e4SLinus Torvalds }
2171da177e4SLinus Torvalds 
218352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
219352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
220cb53c626STakashi Iwai 			      int dir, int idx)
221cb53c626STakashi Iwai {
222352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
223352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
224352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
225cb53c626STakashi Iwai }
226352f7f91STakashi Iwai 
2270c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
2280c8c0f56STakashi Iwai {
2290c8c0f56STakashi Iwai 	char buf[40];
2300c8c0f56STakashi Iwai 	int i;
2310c8c0f56STakashi Iwai 
2320c8c0f56STakashi Iwai 
2330c8c0f56STakashi Iwai 	buf[0] = 0;
2340c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
2350c8c0f56STakashi Iwai 		char tmp[4];
2360c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
2370c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
2380c8c0f56STakashi Iwai 	}
2390c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
2400c8c0f56STakashi Iwai }
2410c8c0f56STakashi Iwai 
242352f7f91STakashi Iwai /* called recursively */
243352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
244352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
245352f7f91STakashi Iwai 			     int with_aa_mix, struct nid_path *path, int depth)
246352f7f91STakashi Iwai {
247352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
248ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
249352f7f91STakashi Iwai 	int i, nums;
250352f7f91STakashi Iwai 
251352f7f91STakashi Iwai 	if (to_nid == spec->mixer_nid) {
2524ac0eefaSTakashi Iwai 		if (with_aa_mix == HDA_PARSE_NO_AAMIX)
253352f7f91STakashi Iwai 			return false;
2544ac0eefaSTakashi Iwai 		with_aa_mix = HDA_PARSE_ALL; /* mark aa-mix is included */
255352f7f91STakashi Iwai 	}
256352f7f91STakashi Iwai 
257ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
258352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
259352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
260352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
261352f7f91STakashi Iwai 			 * try to find an empty DAC
262352f7f91STakashi Iwai 			 */
263352f7f91STakashi Iwai 			if (from_nid ||
264352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
265352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
266352f7f91STakashi Iwai 				continue;
267352f7f91STakashi Iwai 		}
268352f7f91STakashi Iwai 		/* aa-mix is requested but not included? */
2694ac0eefaSTakashi Iwai 		if (!(spec->mixer_nid && with_aa_mix == HDA_PARSE_ONLY_AAMIX))
270352f7f91STakashi Iwai 			goto found;
271352f7f91STakashi Iwai 	}
272352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
273352f7f91STakashi Iwai 		return false;
274352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
275352f7f91STakashi Iwai 		unsigned int type;
276352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
277352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
278352f7f91STakashi Iwai 		    type == AC_WID_PIN)
279352f7f91STakashi Iwai 			continue;
280352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
281352f7f91STakashi Iwai 				     with_aa_mix, path, depth + 1))
282352f7f91STakashi Iwai 			goto found;
283352f7f91STakashi Iwai 	}
284352f7f91STakashi Iwai 	return false;
285352f7f91STakashi Iwai 
286352f7f91STakashi Iwai  found:
287352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
288f5172a7eSTakashi Iwai 	if (conn[i] == spec->mixer_nid)
289f5172a7eSTakashi Iwai 		path->with_aa_mix = true;
290352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
291352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
292352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
293352f7f91STakashi Iwai 	path->depth++;
294352f7f91STakashi Iwai 	return true;
295352f7f91STakashi Iwai }
296352f7f91STakashi Iwai 
297352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
298352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
2994ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_NO_AAMIX, paths with spec->mixer_nid are
3004ac0eefaSTakashi Iwai  * excluded, only the paths that don't go through the mixer will be chosen.
3014ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_ONLY_AAMIX, only the paths going through
3024ac0eefaSTakashi Iwai  * spec->mixer_nid will be chosen.
3034ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_ALL, no special handling about mixer widget.
304352f7f91STakashi Iwai  */
305352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
306352f7f91STakashi Iwai 			    hda_nid_t to_nid, int with_aa_mix,
307352f7f91STakashi Iwai 			    struct nid_path *path)
308352f7f91STakashi Iwai {
309352f7f91STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) {
310352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
311352f7f91STakashi Iwai 		path->depth++;
312352f7f91STakashi Iwai 		return true;
313352f7f91STakashi Iwai 	}
314352f7f91STakashi Iwai 	return false;
315352f7f91STakashi Iwai }
316352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
317352f7f91STakashi Iwai 
318352f7f91STakashi Iwai /*
319352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
320352f7f91STakashi Iwai  * if no valid path is found, return NULL
321352f7f91STakashi Iwai  */
322352f7f91STakashi Iwai struct nid_path *
323352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
324352f7f91STakashi Iwai 		     hda_nid_t to_nid, int with_aa_mix)
325352f7f91STakashi Iwai {
326352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
327352f7f91STakashi Iwai 	struct nid_path *path;
328352f7f91STakashi Iwai 
329352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
330352f7f91STakashi Iwai 		return NULL;
331352f7f91STakashi Iwai 
332f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
333f5172a7eSTakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, with_aa_mix);
334f5172a7eSTakashi Iwai 	if (path)
335f5172a7eSTakashi Iwai 		return path;
336f5172a7eSTakashi Iwai 
337352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
338352f7f91STakashi Iwai 	if (!path)
339352f7f91STakashi Iwai 		return NULL;
340352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
341352f7f91STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path))
342352f7f91STakashi Iwai 		return path;
343352f7f91STakashi Iwai 	/* push back */
344352f7f91STakashi Iwai 	spec->paths.used--;
345352f7f91STakashi Iwai 	return NULL;
346352f7f91STakashi Iwai }
347352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
348352f7f91STakashi Iwai 
349352f7f91STakashi Iwai /* look for an empty DAC slot */
350352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
351352f7f91STakashi Iwai 			      bool is_digital)
352352f7f91STakashi Iwai {
353352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
354352f7f91STakashi Iwai 	bool cap_digital;
355352f7f91STakashi Iwai 	int i;
356352f7f91STakashi Iwai 
357352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
358352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
359352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
360352f7f91STakashi Iwai 			continue;
361352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
362352f7f91STakashi Iwai 		if (is_digital != cap_digital)
363352f7f91STakashi Iwai 			continue;
364352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
365352f7f91STakashi Iwai 			return nid;
366352f7f91STakashi Iwai 	}
367352f7f91STakashi Iwai 	return 0;
368352f7f91STakashi Iwai }
369352f7f91STakashi Iwai 
370352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
371352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
372352f7f91STakashi Iwai {
373352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
374352f7f91STakashi Iwai 	val |= chs << 16;
375352f7f91STakashi Iwai 	return val;
376352f7f91STakashi Iwai }
377352f7f91STakashi Iwai 
378352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
379352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
380352f7f91STakashi Iwai 			   int dir, unsigned int bits)
381352f7f91STakashi Iwai {
382352f7f91STakashi Iwai 	if (!nid)
383352f7f91STakashi Iwai 		return false;
384352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
385352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
386352f7f91STakashi Iwai 			return true;
387352f7f91STakashi Iwai 	return false;
388352f7f91STakashi Iwai }
389352f7f91STakashi Iwai 
390352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
391352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
392352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
393352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
394352f7f91STakashi Iwai 
395352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
396352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
397352f7f91STakashi Iwai 				       struct nid_path *path)
398352f7f91STakashi Iwai {
399352f7f91STakashi Iwai 	int i;
400352f7f91STakashi Iwai 
401352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
402352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
403352f7f91STakashi Iwai 			return path->path[i];
404352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
405352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
406352f7f91STakashi Iwai 			return path->path[i];
407352f7f91STakashi Iwai 	}
408352f7f91STakashi Iwai 	return 0;
409352f7f91STakashi Iwai }
410352f7f91STakashi Iwai 
411352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
412352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
413352f7f91STakashi Iwai 				      struct nid_path *path)
414352f7f91STakashi Iwai {
415352f7f91STakashi Iwai 	int i;
416352f7f91STakashi Iwai 
417352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
418352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
419352f7f91STakashi Iwai 			return path->path[i];
420352f7f91STakashi Iwai 	}
421352f7f91STakashi Iwai 	return 0;
422352f7f91STakashi Iwai }
423352f7f91STakashi Iwai 
424352f7f91STakashi Iwai /*
425352f7f91STakashi Iwai  * path activation / deactivation
426352f7f91STakashi Iwai  */
427352f7f91STakashi Iwai 
428352f7f91STakashi Iwai /* can have the amp-in capability? */
429352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
430352f7f91STakashi Iwai {
431352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
432352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
433352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
434352f7f91STakashi Iwai 
435352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
436352f7f91STakashi Iwai 		return false;
437352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
438352f7f91STakashi Iwai 		return false;
439352f7f91STakashi Iwai 	return true;
440352f7f91STakashi Iwai }
441352f7f91STakashi Iwai 
442352f7f91STakashi Iwai /* can have the amp-out capability? */
443352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
444352f7f91STakashi Iwai {
445352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
446352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
447352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
448352f7f91STakashi Iwai 
449352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
450352f7f91STakashi Iwai 		return false;
451352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
452352f7f91STakashi Iwai 		return false;
453352f7f91STakashi Iwai 	return true;
454352f7f91STakashi Iwai }
455352f7f91STakashi Iwai 
456352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
457352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
458352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
459352f7f91STakashi Iwai {
460352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
461352f7f91STakashi Iwai 	int i, n;
462352f7f91STakashi Iwai 
463352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
464352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
465352f7f91STakashi Iwai 		if (!path->active)
466352f7f91STakashi Iwai 			continue;
467352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
468352f7f91STakashi Iwai 			if (path->path[i] == nid) {
469352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
470352f7f91STakashi Iwai 					return true;
471352f7f91STakashi Iwai 				break;
472352f7f91STakashi Iwai 			}
473352f7f91STakashi Iwai 		}
474352f7f91STakashi Iwai 	}
475352f7f91STakashi Iwai 	return false;
476352f7f91STakashi Iwai }
477352f7f91STakashi Iwai 
478352f7f91STakashi Iwai /* get the default amp value for the target state */
479352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
480352f7f91STakashi Iwai 				   int dir, bool enable)
481352f7f91STakashi Iwai {
482352f7f91STakashi Iwai 	unsigned int caps;
483352f7f91STakashi Iwai 	unsigned int val = 0;
484352f7f91STakashi Iwai 
485352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
486352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
487352f7f91STakashi Iwai 		/* set to 0dB */
488352f7f91STakashi Iwai 		if (enable)
489352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
490352f7f91STakashi Iwai 	}
491352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
492352f7f91STakashi Iwai 		if (!enable)
493352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
494352f7f91STakashi Iwai 	}
495352f7f91STakashi Iwai 	return val;
496352f7f91STakashi Iwai }
497352f7f91STakashi Iwai 
498352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
499352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
500352f7f91STakashi Iwai {
501352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
502352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
503352f7f91STakashi Iwai }
504352f7f91STakashi Iwai 
505352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
506352f7f91STakashi Iwai 			 int idx, bool enable)
507352f7f91STakashi Iwai {
508352f7f91STakashi Iwai 	int val;
509352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
510985803caSTakashi Iwai 	    (!enable && is_active_nid(codec, nid, dir, idx)))
511352f7f91STakashi Iwai 		return;
512352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
513352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
514352f7f91STakashi Iwai }
515352f7f91STakashi Iwai 
516352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
517352f7f91STakashi Iwai 			     int i, bool enable)
518352f7f91STakashi Iwai {
519352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
520352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
521352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
522352f7f91STakashi Iwai }
523352f7f91STakashi Iwai 
524352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
525352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
526352f7f91STakashi Iwai {
527352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
528ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
529352f7f91STakashi Iwai 	int n, nums, idx;
530352f7f91STakashi Iwai 	int type;
531352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
532352f7f91STakashi Iwai 
533ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
534352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
535352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
536352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
537352f7f91STakashi Iwai 		nums = 1;
538352f7f91STakashi Iwai 		idx = 0;
539352f7f91STakashi Iwai 	} else
540352f7f91STakashi Iwai 		idx = path->idx[i];
541352f7f91STakashi Iwai 
542352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
543352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
544352f7f91STakashi Iwai 
545352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
546352f7f91STakashi Iwai 		return;
547352f7f91STakashi Iwai 
548352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
549352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
550352f7f91STakashi Iwai 	 */
551352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
552352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
553352f7f91STakashi Iwai 			continue;
554352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
555352f7f91STakashi Iwai 	}
556352f7f91STakashi Iwai }
557352f7f91STakashi Iwai 
558352f7f91STakashi Iwai /* activate or deactivate the given path
559352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
560352f7f91STakashi Iwai  */
561352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
562352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
563352f7f91STakashi Iwai {
564352f7f91STakashi Iwai 	int i;
565352f7f91STakashi Iwai 
566352f7f91STakashi Iwai 	if (!enable)
567352f7f91STakashi Iwai 		path->active = false;
568352f7f91STakashi Iwai 
569352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
570352f7f91STakashi Iwai 		if (enable && path->multi[i])
571352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
572352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
573352f7f91STakashi Iwai 					    path->idx[i]);
574352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
575352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
576352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
577352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
578352f7f91STakashi Iwai 	}
579352f7f91STakashi Iwai 
580352f7f91STakashi Iwai 	if (enable)
581352f7f91STakashi Iwai 		path->active = true;
582352f7f91STakashi Iwai }
583352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
584352f7f91STakashi Iwai 
585d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
586d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
587d5a9f1bbSTakashi Iwai {
588d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
589d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
590d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
591d5a9f1bbSTakashi Iwai 		return;
592ecac3ed1STakashi Iwai 	if (codec->inv_eapd)
593ecac3ed1STakashi Iwai 		enable = !enable;
594d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
595d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
596d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
597d5a9f1bbSTakashi Iwai }
598d5a9f1bbSTakashi Iwai 
599352f7f91STakashi Iwai 
600352f7f91STakashi Iwai /*
601352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
602352f7f91STakashi Iwai  */
603352f7f91STakashi Iwai 
604352f7f91STakashi Iwai enum {
605352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
606352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
607352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
608352f7f91STakashi Iwai 	HDA_CTL_BIND_VOL,
609352f7f91STakashi Iwai 	HDA_CTL_BIND_SW,
610352f7f91STakashi Iwai };
611352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
612352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
613352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
614352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
615352f7f91STakashi Iwai 	HDA_BIND_VOL(NULL, 0),
616352f7f91STakashi Iwai 	HDA_BIND_SW(NULL, 0),
617352f7f91STakashi Iwai };
618352f7f91STakashi Iwai 
619352f7f91STakashi Iwai /* add dynamic controls from template */
620352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
621352f7f91STakashi Iwai 		       int cidx, unsigned long val)
622352f7f91STakashi Iwai {
623352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
624352f7f91STakashi Iwai 
62512c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
626352f7f91STakashi Iwai 	if (!knew)
627352f7f91STakashi Iwai 		return -ENOMEM;
628352f7f91STakashi Iwai 	knew->index = cidx;
629352f7f91STakashi Iwai 	if (get_amp_nid_(val))
630352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
631352f7f91STakashi Iwai 	knew->private_value = val;
632352f7f91STakashi Iwai 	return 0;
633352f7f91STakashi Iwai }
634352f7f91STakashi Iwai 
635352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
636352f7f91STakashi Iwai 				const char *pfx, const char *dir,
637352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
638352f7f91STakashi Iwai {
639352f7f91STakashi Iwai 	char name[32];
640352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
641352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
642352f7f91STakashi Iwai }
643352f7f91STakashi Iwai 
644352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
645352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
646352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
647352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
648352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
649352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
650352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
651352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
652352f7f91STakashi Iwai 
653352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
654352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
655352f7f91STakashi Iwai {
656352f7f91STakashi Iwai 	unsigned int val;
657352f7f91STakashi Iwai 	if (!path)
658352f7f91STakashi Iwai 		return 0;
659352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
660352f7f91STakashi Iwai 	if (!val)
661352f7f91STakashi Iwai 		return 0;
662352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
663352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
664352f7f91STakashi Iwai }
665352f7f91STakashi Iwai 
666352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
667352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
668352f7f91STakashi Iwai 			       int type)
669352f7f91STakashi Iwai {
670352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
671352f7f91STakashi Iwai 	if (path) {
672352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
673352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
674352f7f91STakashi Iwai 			chs = 3; /* stereo */
675352f7f91STakashi Iwai 	}
676352f7f91STakashi Iwai 	return chs;
677352f7f91STakashi Iwai }
678352f7f91STakashi Iwai 
679352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
680352f7f91STakashi Iwai 			  struct nid_path *path)
681352f7f91STakashi Iwai {
682352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
683352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
684352f7f91STakashi Iwai }
685352f7f91STakashi Iwai 
686352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
687352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
688352f7f91STakashi Iwai  */
689352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
690352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
691352f7f91STakashi Iwai {
692352f7f91STakashi Iwai 	unsigned int val;
693352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
694352f7f91STakashi Iwai 
695352f7f91STakashi Iwai 	if (!path)
696352f7f91STakashi Iwai 		return 0;
697352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
698352f7f91STakashi Iwai 	if (!val)
699352f7f91STakashi Iwai 		return 0;
700352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
701352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
702352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
703352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
704352f7f91STakashi Iwai 		if (nums > 1) {
705352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
706352f7f91STakashi Iwai 			val |= nums << 19;
707352f7f91STakashi Iwai 		}
708352f7f91STakashi Iwai 	}
709352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
710352f7f91STakashi Iwai }
711352f7f91STakashi Iwai 
712352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
713352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
714352f7f91STakashi Iwai {
715352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
716352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
717352f7f91STakashi Iwai }
718352f7f91STakashi Iwai 
719352f7f91STakashi Iwai static const char * const channel_name[4] = {
720352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
721352f7f91STakashi Iwai };
722352f7f91STakashi Iwai 
723352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
724352f7f91STakashi Iwai static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch,
725352f7f91STakashi Iwai 				    bool can_be_master, int *index)
726352f7f91STakashi Iwai {
727352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
728352f7f91STakashi Iwai 
729352f7f91STakashi Iwai 	*index = 0;
730352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
731352f7f91STakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
732352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
733352f7f91STakashi Iwai 
734352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
735352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
736352f7f91STakashi Iwai 	 */
737352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
738352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
739352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
740352f7f91STakashi Iwai 
741352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
742352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
743352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
744352f7f91STakashi Iwai 			return "Speaker";
745352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
746352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
747352f7f91STakashi Iwai 		break;
748352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
749352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
750352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
751352f7f91STakashi Iwai 			break;
752352f7f91STakashi Iwai 		*index = ch;
753352f7f91STakashi Iwai 		return "Headphone";
754352f7f91STakashi Iwai 	default:
755352f7f91STakashi Iwai 		if (cfg->line_outs == 1 && !spec->multi_ios)
756352f7f91STakashi Iwai 			return "PCM";
757352f7f91STakashi Iwai 		break;
758352f7f91STakashi Iwai 	}
759352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
760352f7f91STakashi Iwai 		snd_BUG();
761352f7f91STakashi Iwai 		return "PCM";
762352f7f91STakashi Iwai 	}
763352f7f91STakashi Iwai 
764352f7f91STakashi Iwai 	return channel_name[ch];
765352f7f91STakashi Iwai }
766352f7f91STakashi Iwai 
767352f7f91STakashi Iwai /*
768352f7f91STakashi Iwai  * Parse output paths
769352f7f91STakashi Iwai  */
770352f7f91STakashi Iwai 
771352f7f91STakashi Iwai /* badness definition */
772352f7f91STakashi Iwai enum {
773352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
774352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
775352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
776352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
777352f7f91STakashi Iwai 	/* No possible multi-ios */
778352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
779352f7f91STakashi Iwai 	/* No individual DAC for extra output */
780352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
781352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
782352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
783352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
784352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
785352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
786352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
787352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
788352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
789352f7f91STakashi Iwai 	/* Volume widget is shared */
790352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
791352f7f91STakashi Iwai };
792352f7f91STakashi Iwai 
793352f7f91STakashi Iwai /* look for widgets in the path between the given NIDs appropriate for
794352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
795352f7f91STakashi Iwai  *
796352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
797352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
798352f7f91STakashi Iwai  * total badness for both volume and mute controls.
799352f7f91STakashi Iwai  */
800352f7f91STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, hda_nid_t pin,
801352f7f91STakashi Iwai 				hda_nid_t dac)
802352f7f91STakashi Iwai {
803352f7f91STakashi Iwai 	struct nid_path *path = snd_hda_get_nid_path(codec, dac, pin);
804352f7f91STakashi Iwai 	hda_nid_t nid;
805352f7f91STakashi Iwai 	unsigned int val;
806352f7f91STakashi Iwai 	int badness = 0;
807352f7f91STakashi Iwai 
808352f7f91STakashi Iwai 	if (!path)
809352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
810352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
811352f7f91STakashi Iwai 	if (nid) {
812352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
813352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
814352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
815352f7f91STakashi Iwai 		else
816352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
817352f7f91STakashi Iwai 	} else
818352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
819352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
820352f7f91STakashi Iwai 	if (nid) {
821352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
822352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
823352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
824352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
825352f7f91STakashi Iwai 		else
826352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
827352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
828352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
829352f7f91STakashi Iwai 		else
830352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
831352f7f91STakashi Iwai 	} else
832352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
833352f7f91STakashi Iwai 	return badness;
834352f7f91STakashi Iwai }
835352f7f91STakashi Iwai 
836352f7f91STakashi Iwai struct badness_table {
837352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
838352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
839352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
840352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
841352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
842352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
843352f7f91STakashi Iwai };
844352f7f91STakashi Iwai 
845352f7f91STakashi Iwai static struct badness_table main_out_badness = {
846352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
847352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
848352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
849352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
850352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
851352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
852352f7f91STakashi Iwai };
853352f7f91STakashi Iwai 
854352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
855352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
856352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
857352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
858352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
859352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
860352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
861352f7f91STakashi Iwai };
862352f7f91STakashi Iwai 
8637385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
8647385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
8657385df61STakashi Iwai {
8667385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
8677385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
8687385df61STakashi Iwai 
8697385df61STakashi Iwai 	if (cfg->line_outs > idx)
8707385df61STakashi Iwai 		return spec->private_dac_nids[idx];
8717385df61STakashi Iwai 	idx -= cfg->line_outs;
8727385df61STakashi Iwai 	if (spec->multi_ios > idx)
8737385df61STakashi Iwai 		return spec->multi_io[idx].dac;
8747385df61STakashi Iwai 	return 0;
8757385df61STakashi Iwai }
8767385df61STakashi Iwai 
8777385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
8787385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
8797385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
8807385df61STakashi Iwai {
8817385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
8827385df61STakashi Iwai }
8837385df61STakashi Iwai 
884352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
885352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
886352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
887196c1766STakashi Iwai 			   int *path_idx,
888352f7f91STakashi Iwai 			   const struct badness_table *bad)
889352f7f91STakashi Iwai {
890352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
891352f7f91STakashi Iwai 	int i, j;
892352f7f91STakashi Iwai 	int badness = 0;
893352f7f91STakashi Iwai 	hda_nid_t dac;
894352f7f91STakashi Iwai 
895352f7f91STakashi Iwai 	if (!num_outs)
896352f7f91STakashi Iwai 		return 0;
897352f7f91STakashi Iwai 
898352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
8990c8c0f56STakashi Iwai 		struct nid_path *path;
900352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
9011e0b5286STakashi Iwai 
9021e0b5286STakashi Iwai 		if (dacs[i]) {
9031e0b5286STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dacs[i]);
9041e0b5286STakashi Iwai 			continue;
9051e0b5286STakashi Iwai 		}
9061e0b5286STakashi Iwai 
907352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
908352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
909352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
910352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
911352f7f91STakashi Iwai 					dacs[0] = dacs[j];
912352f7f91STakashi Iwai 					dacs[j] = 0;
913196c1766STakashi Iwai 					path_idx[j] = 0;
914352f7f91STakashi Iwai 					break;
915352f7f91STakashi Iwai 				}
916352f7f91STakashi Iwai 			}
917352f7f91STakashi Iwai 		}
918352f7f91STakashi Iwai 		dac = dacs[i];
919352f7f91STakashi Iwai 		if (!dac) {
9207385df61STakashi Iwai 			if (num_outs > 2)
9217385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
9227385df61STakashi Iwai 			if (!dac)
9237385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
9247385df61STakashi Iwai 			if (!dac)
9257385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
926352f7f91STakashi Iwai 			if (dac) {
927352f7f91STakashi Iwai 				if (!i)
928352f7f91STakashi Iwai 					badness += bad->shared_primary;
929352f7f91STakashi Iwai 				else if (i == 1)
930352f7f91STakashi Iwai 					badness += bad->shared_surr;
931352f7f91STakashi Iwai 				else
932352f7f91STakashi Iwai 					badness += bad->shared_clfe;
933352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
934352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
935352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
936352f7f91STakashi Iwai 			} else if (!i)
937352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
938352f7f91STakashi Iwai 			else
939352f7f91STakashi Iwai 				badness += bad->no_dac;
940352f7f91STakashi Iwai 		}
9414ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_NO_AAMIX);
942117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
943b3a8c745STakashi Iwai 			/* try with aamix */
944b3a8c745STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_ALL);
945b3a8c745STakashi Iwai 		}
9460c8c0f56STakashi Iwai 		if (!path)
947352f7f91STakashi Iwai 			dac = dacs[i] = 0;
948e1284af7STakashi Iwai 		else {
9490c8c0f56STakashi Iwai 			print_nid_path("output", path);
950e1284af7STakashi Iwai 			path->active = true;
951196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
952e1284af7STakashi Iwai 		}
953352f7f91STakashi Iwai 		if (dac)
954352f7f91STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dac);
955352f7f91STakashi Iwai 	}
956352f7f91STakashi Iwai 
957352f7f91STakashi Iwai 	return badness;
958352f7f91STakashi Iwai }
959352f7f91STakashi Iwai 
960352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
961352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
962352f7f91STakashi Iwai {
963352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
964352f7f91STakashi Iwai 	int i;
965352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
966352f7f91STakashi Iwai 
967352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
968352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
969352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
970352f7f91STakashi Iwai 			continue;
971352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
972352f7f91STakashi Iwai 			if (nid_found)
973352f7f91STakashi Iwai 				return 0;
974352f7f91STakashi Iwai 			nid_found = nid;
975352f7f91STakashi Iwai 		}
976352f7f91STakashi Iwai 	}
977352f7f91STakashi Iwai 	return nid_found;
978352f7f91STakashi Iwai }
979352f7f91STakashi Iwai 
980352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
981352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
982352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
983352f7f91STakashi Iwai {
984352f7f91STakashi Iwai 	unsigned int defcfg, caps;
985352f7f91STakashi Iwai 
986352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
987352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
988352f7f91STakashi Iwai 		return false;
989352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
990352f7f91STakashi Iwai 		return false;
991352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
992352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
993352f7f91STakashi Iwai 		return false;
994352f7f91STakashi Iwai 	return true;
995352f7f91STakashi Iwai }
996352f7f91STakashi Iwai 
997e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
998e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
999e22aab7dSTakashi Iwai {
1000e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1001e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1002e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1003e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1004e22aab7dSTakashi Iwai 	int type, i;
1005e22aab7dSTakashi Iwai 	int num_pins = 0;
1006e22aab7dSTakashi Iwai 
1007e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1008e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1009e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1010e22aab7dSTakashi Iwai 				continue;
1011e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1012e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1013e22aab7dSTakashi Iwai 				num_pins++;
1014e22aab7dSTakashi Iwai 		}
1015e22aab7dSTakashi Iwai 	}
1016e22aab7dSTakashi Iwai 	return num_pins;
1017e22aab7dSTakashi Iwai }
1018e22aab7dSTakashi Iwai 
1019352f7f91STakashi Iwai /*
1020352f7f91STakashi Iwai  * multi-io helper
1021352f7f91STakashi Iwai  *
1022352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1023352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1024352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1025352f7f91STakashi Iwai  * the badness value.
1026352f7f91STakashi Iwai  */
1027352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1028352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1029e22aab7dSTakashi Iwai 			  bool hardwired)
1030352f7f91STakashi Iwai {
1031352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1032352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1033e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1034352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1035352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1036352f7f91STakashi Iwai 	int badness = 0;
1037352f7f91STakashi Iwai 
1038352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1039352f7f91STakashi Iwai 	if (old_pins >= 2)
1040352f7f91STakashi Iwai 		goto end_fill;
1041352f7f91STakashi Iwai 
1042e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1043352f7f91STakashi Iwai 	if (num_pins < 2)
1044352f7f91STakashi Iwai 		goto end_fill;
1045352f7f91STakashi Iwai 
1046352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1047352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
10480c8c0f56STakashi Iwai 			struct nid_path *path;
1049352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1050352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1051352f7f91STakashi Iwai 
1052352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1053352f7f91STakashi Iwai 				continue;
1054352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1055352f7f91STakashi Iwai 				continue;
1056352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1057352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1058352f7f91STakashi Iwai 					break;
1059352f7f91STakashi Iwai 			}
1060352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1061352f7f91STakashi Iwai 				continue;
1062352f7f91STakashi Iwai 
1063352f7f91STakashi Iwai 			if (hardwired)
1064352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1065352f7f91STakashi Iwai 			else if (!dac)
1066352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1067352f7f91STakashi Iwai 			if (!dac) {
1068352f7f91STakashi Iwai 				badness++;
1069352f7f91STakashi Iwai 				continue;
1070352f7f91STakashi Iwai 			}
10714ac0eefaSTakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid, HDA_PARSE_NO_AAMIX);
10720c8c0f56STakashi Iwai 			if (!path) {
1073352f7f91STakashi Iwai 				badness++;
1074352f7f91STakashi Iwai 				continue;
1075352f7f91STakashi Iwai 			}
10760c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1077352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1078352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1079196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1080196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1081352f7f91STakashi Iwai 			spec->multi_ios++;
1082352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1083352f7f91STakashi Iwai 				break;
1084352f7f91STakashi Iwai 		}
1085352f7f91STakashi Iwai 	}
1086352f7f91STakashi Iwai  end_fill:
1087352f7f91STakashi Iwai 	if (badness)
1088352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1089352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1090352f7f91STakashi Iwai 		if (hardwired)
1091352f7f91STakashi Iwai 			return 1; /* nothing found */
1092352f7f91STakashi Iwai 		else
1093352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1094352f7f91STakashi Iwai 	}
1095352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1096352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1097352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1098352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1099352f7f91STakashi Iwai 		return badness;
1100352f7f91STakashi Iwai 	}
1101352f7f91STakashi Iwai 
1102352f7f91STakashi Iwai 	/* assign volume and mute controls */
1103352f7f91STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++)
1104352f7f91STakashi Iwai 		badness += assign_out_path_ctls(codec, spec->multi_io[i].pin,
1105352f7f91STakashi Iwai 						spec->multi_io[i].dac);
1106352f7f91STakashi Iwai 
1107352f7f91STakashi Iwai 	return badness;
1108352f7f91STakashi Iwai }
1109352f7f91STakashi Iwai 
1110352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1111352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1112196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1113352f7f91STakashi Iwai {
1114b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1115352f7f91STakashi Iwai 	int i;
1116352f7f91STakashi Iwai 	bool found = false;
1117352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
11180c8c0f56STakashi Iwai 		struct nid_path *path;
1119352f7f91STakashi Iwai 		hda_nid_t dac;
1120352f7f91STakashi Iwai 		if (dacs[i])
1121352f7f91STakashi Iwai 			continue;
1122352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1123352f7f91STakashi Iwai 		if (!dac)
1124352f7f91STakashi Iwai 			continue;
11254ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_NO_AAMIX);
1126117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
1127b3a8c745STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_ALL);
11280c8c0f56STakashi Iwai 		if (path) {
1129352f7f91STakashi Iwai 			dacs[i] = dac;
1130352f7f91STakashi Iwai 			found = true;
11310c8c0f56STakashi Iwai 			print_nid_path("output", path);
1132e1284af7STakashi Iwai 			path->active = true;
1133196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1134352f7f91STakashi Iwai 		}
1135352f7f91STakashi Iwai 	}
1136352f7f91STakashi Iwai 	return found;
1137352f7f91STakashi Iwai }
1138352f7f91STakashi Iwai 
1139c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1140c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1141c30aa7b2STakashi Iwai {
1142c30aa7b2STakashi Iwai 	struct nid_path *path;
1143c30aa7b2STakashi Iwai 
1144c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1145c30aa7b2STakashi Iwai 	if (!path || !path->depth || path->with_aa_mix)
1146c30aa7b2STakashi Iwai 		return 0;
1147c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1148c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
1149c30aa7b2STakashi Iwai 				    HDA_PARSE_ONLY_AAMIX);
1150c30aa7b2STakashi Iwai 	if (!path)
1151c30aa7b2STakashi Iwai 		return 0;
1152c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1153c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1154c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1155c30aa7b2STakashi Iwai }
1156c30aa7b2STakashi Iwai 
1157352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1158352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1159352f7f91STakashi Iwai 			      bool fill_hardwired,
1160352f7f91STakashi Iwai 			      bool fill_mio_first)
1161352f7f91STakashi Iwai {
1162352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1163352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1164352f7f91STakashi Iwai 	int i, err, badness;
1165352f7f91STakashi Iwai 
1166352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1167352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1168352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1169352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1170352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1171352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1172352f7f91STakashi Iwai 	spec->multi_ios = 0;
1173352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1174352f7f91STakashi Iwai 	badness = 0;
1175352f7f91STakashi Iwai 
1176352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1177352f7f91STakashi Iwai 	if (fill_hardwired) {
1178352f7f91STakashi Iwai 		bool mapped;
1179352f7f91STakashi Iwai 		do {
1180352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1181352f7f91STakashi Iwai 					     cfg->line_out_pins,
1182196c1766STakashi Iwai 					     spec->private_dac_nids,
1183196c1766STakashi Iwai 					     spec->out_paths);
1184352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1185352f7f91STakashi Iwai 					      cfg->hp_pins,
1186196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1187196c1766STakashi Iwai 					      spec->hp_paths);
1188352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1189352f7f91STakashi Iwai 					      cfg->speaker_pins,
1190196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1191196c1766STakashi Iwai 					      spec->speaker_paths);
1192352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1193352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1194e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1195352f7f91STakashi Iwai 				if (!err)
1196352f7f91STakashi Iwai 					mapped = true;
1197352f7f91STakashi Iwai 			}
1198352f7f91STakashi Iwai 		} while (mapped);
1199352f7f91STakashi Iwai 	}
1200352f7f91STakashi Iwai 
1201352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1202196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1203352f7f91STakashi Iwai 				   &main_out_badness);
1204352f7f91STakashi Iwai 
1205352f7f91STakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1206352f7f91STakashi Iwai 	spec->multiout.num_dacs = 0;
1207352f7f91STakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1208352f7f91STakashi Iwai 		if (spec->private_dac_nids[i])
1209352f7f91STakashi Iwai 			spec->multiout.num_dacs++;
1210352f7f91STakashi Iwai 		else {
1211352f7f91STakashi Iwai 			memmove(spec->private_dac_nids + i,
1212352f7f91STakashi Iwai 				spec->private_dac_nids + i + 1,
1213352f7f91STakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1214352f7f91STakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1215352f7f91STakashi Iwai 		}
1216352f7f91STakashi Iwai 	}
1217352f7f91STakashi Iwai 
1218352f7f91STakashi Iwai 	if (fill_mio_first &&
1219352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1220352f7f91STakashi Iwai 		/* try to fill multi-io first */
1221e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1222352f7f91STakashi Iwai 		if (err < 0)
1223352f7f91STakashi Iwai 			return err;
1224352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1225352f7f91STakashi Iwai 	}
1226352f7f91STakashi Iwai 
1227352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1228352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1229352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1230196c1766STakashi Iwai 				      spec->hp_paths,
1231352f7f91STakashi Iwai 				      &extra_out_badness);
1232352f7f91STakashi Iwai 		if (err < 0)
1233352f7f91STakashi Iwai 			return err;
1234352f7f91STakashi Iwai 		badness += err;
1235352f7f91STakashi Iwai 	}
1236352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1237352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1238352f7f91STakashi Iwai 				      cfg->speaker_pins,
1239352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1240196c1766STakashi Iwai 				      spec->speaker_paths,
1241352f7f91STakashi Iwai 				      &extra_out_badness);
1242352f7f91STakashi Iwai 		if (err < 0)
1243352f7f91STakashi Iwai 			return err;
1244352f7f91STakashi Iwai 		badness += err;
1245352f7f91STakashi Iwai 	}
1246352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1247e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1248352f7f91STakashi Iwai 		if (err < 0)
1249352f7f91STakashi Iwai 			return err;
1250352f7f91STakashi Iwai 		badness += err;
1251352f7f91STakashi Iwai 	}
1252e22aab7dSTakashi Iwai 
1253c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1254c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1255c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1256c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1257c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1258c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1259c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1260c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1261c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1262c30aa7b2STakashi Iwai 	}
1263c30aa7b2STakashi Iwai 
1264e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1265e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1266e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1267352f7f91STakashi Iwai 
1268352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1269352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1270352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1271352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1272352f7f91STakashi Iwai 		spec->ext_channel_count = 2;
1273352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1274352f7f91STakashi Iwai 		spec->multi_ios = 0;
1275352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1276352f7f91STakashi Iwai 	}
1277352f7f91STakashi Iwai 
1278352f7f91STakashi Iwai 	return badness;
1279352f7f91STakashi Iwai }
1280352f7f91STakashi Iwai 
1281352f7f91STakashi Iwai #define DEBUG_BADNESS
1282352f7f91STakashi Iwai 
1283352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1284352f7f91STakashi Iwai #define debug_badness	snd_printdd
1285352f7f91STakashi Iwai #else
1286352f7f91STakashi Iwai #define debug_badness(...)
1287352f7f91STakashi Iwai #endif
1288352f7f91STakashi Iwai 
1289352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1290352f7f91STakashi Iwai {
1291352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1292352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1293708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1294352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1295352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1296352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1297352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1298352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1299352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1300352f7f91STakashi Iwai 			      spec->multi_ios,
1301352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1302352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1303352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1304352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1305708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1306352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1307352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1308352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1309352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1310352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1311352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1312352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1313352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1314352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1315352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1316352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1317352f7f91STakashi Iwai }
1318352f7f91STakashi Iwai 
1319352f7f91STakashi Iwai /* find all available DACs of the codec */
1320352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1321352f7f91STakashi Iwai {
1322352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1323352f7f91STakashi Iwai 	int i;
1324352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1325352f7f91STakashi Iwai 
1326352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1327352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1328352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1329352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1330352f7f91STakashi Iwai 			continue;
1331352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1332352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1333352f7f91STakashi Iwai 			break;
1334352f7f91STakashi Iwai 		}
1335352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1336352f7f91STakashi Iwai 	}
1337352f7f91STakashi Iwai }
1338352f7f91STakashi Iwai 
1339352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1340352f7f91STakashi Iwai {
1341352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1342352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1343352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1344352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1345352f7f91STakashi Iwai 	int badness;
1346352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1347352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1348352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1349352f7f91STakashi Iwai 
1350352f7f91STakashi Iwai 	fill_all_dac_nids(codec);
1351352f7f91STakashi Iwai 
1352352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1353352f7f91STakashi Iwai 	if (!best_cfg)
1354352f7f91STakashi Iwai 		return -ENOMEM;
1355352f7f91STakashi Iwai 	*best_cfg = *cfg;
1356352f7f91STakashi Iwai 
1357352f7f91STakashi Iwai 	for (;;) {
1358352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1359352f7f91STakashi Iwai 					     fill_mio_first);
1360352f7f91STakashi Iwai 		if (badness < 0) {
1361352f7f91STakashi Iwai 			kfree(best_cfg);
1362352f7f91STakashi Iwai 			return badness;
1363352f7f91STakashi Iwai 		}
1364352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1365352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1366352f7f91STakashi Iwai 			      badness);
1367352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1368352f7f91STakashi Iwai 		if (badness < best_badness) {
1369352f7f91STakashi Iwai 			best_badness = badness;
1370352f7f91STakashi Iwai 			*best_cfg = *cfg;
1371352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1372352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1373352f7f91STakashi Iwai 		}
1374352f7f91STakashi Iwai 		if (!badness)
1375352f7f91STakashi Iwai 			break;
1376352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1377352f7f91STakashi Iwai 		if (!fill_mio_first)
1378352f7f91STakashi Iwai 			continue;
1379352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1380352f7f91STakashi Iwai 		if (!fill_hardwired)
1381352f7f91STakashi Iwai 			continue;
1382352f7f91STakashi Iwai 		if (hp_spk_swapped)
1383352f7f91STakashi Iwai 			break;
1384352f7f91STakashi Iwai 		hp_spk_swapped = true;
1385352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1386352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1387352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1388352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1389352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1390352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1391352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1392352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1393352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1394352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1395352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1396352f7f91STakashi Iwai 			fill_hardwired = true;
1397352f7f91STakashi Iwai 			continue;
1398352f7f91STakashi Iwai 		}
1399352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1400352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1401352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1402352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1403352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1404352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1405352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1406352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1407352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1408352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1409352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1410352f7f91STakashi Iwai 			fill_hardwired = true;
1411352f7f91STakashi Iwai 			continue;
1412352f7f91STakashi Iwai 		}
1413352f7f91STakashi Iwai 		break;
1414352f7f91STakashi Iwai 	}
1415352f7f91STakashi Iwai 
1416352f7f91STakashi Iwai 	if (badness) {
14170c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1418352f7f91STakashi Iwai 		*cfg = *best_cfg;
1419352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1420352f7f91STakashi Iwai 	}
1421352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1422352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1423352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1424352f7f91STakashi Iwai 
1425352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1426352f7f91STakashi Iwai 		struct nid_path *path;
1427196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1428352f7f91STakashi Iwai 		if (path)
1429352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1430352f7f91STakashi Iwai 	}
1431352f7f91STakashi Iwai 
1432352f7f91STakashi Iwai 	kfree(best_cfg);
1433352f7f91STakashi Iwai 	return 0;
1434352f7f91STakashi Iwai }
1435352f7f91STakashi Iwai 
1436352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1437352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1438352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1439352f7f91STakashi Iwai {
1440352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1441352f7f91STakashi Iwai 	int i, err, noutputs;
1442352f7f91STakashi Iwai 
1443352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1444352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1445352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1446352f7f91STakashi Iwai 
1447352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1448352f7f91STakashi Iwai 		const char *name;
1449352f7f91STakashi Iwai 		int index;
1450196c1766STakashi Iwai 		hda_nid_t dac;
1451352f7f91STakashi Iwai 		struct nid_path *path;
1452352f7f91STakashi Iwai 
1453352f7f91STakashi Iwai 		dac = spec->multiout.dac_nids[i];
1454352f7f91STakashi Iwai 		if (!dac)
1455352f7f91STakashi Iwai 			continue;
1456352f7f91STakashi Iwai 		if (i >= cfg->line_outs) {
1457352f7f91STakashi Iwai 			index = 0;
1458352f7f91STakashi Iwai 			name = channel_name[i];
1459352f7f91STakashi Iwai 		} else {
1460352f7f91STakashi Iwai 			name = get_line_out_pfx(spec, i, true, &index);
1461352f7f91STakashi Iwai 		}
1462352f7f91STakashi Iwai 
1463196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1464352f7f91STakashi Iwai 		if (!path)
1465352f7f91STakashi Iwai 			continue;
1466352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1467352f7f91STakashi Iwai 			/* Center/LFE */
1468352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1469352f7f91STakashi Iwai 			if (err < 0)
1470352f7f91STakashi Iwai 				return err;
1471352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1472352f7f91STakashi Iwai 			if (err < 0)
1473352f7f91STakashi Iwai 				return err;
1474352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1475352f7f91STakashi Iwai 			if (err < 0)
1476352f7f91STakashi Iwai 				return err;
1477352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1478352f7f91STakashi Iwai 			if (err < 0)
1479352f7f91STakashi Iwai 				return err;
1480352f7f91STakashi Iwai 		} else {
1481352f7f91STakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1482352f7f91STakashi Iwai 			if (err < 0)
1483352f7f91STakashi Iwai 				return err;
1484352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1485352f7f91STakashi Iwai 			if (err < 0)
1486352f7f91STakashi Iwai 				return err;
1487352f7f91STakashi Iwai 		}
1488352f7f91STakashi Iwai 	}
1489352f7f91STakashi Iwai 	return 0;
1490352f7f91STakashi Iwai }
1491352f7f91STakashi Iwai 
1492352f7f91STakashi Iwai static int create_extra_out(struct hda_codec *codec, hda_nid_t pin,
1493196c1766STakashi Iwai 			    hda_nid_t dac, int path_idx,
1494196c1766STakashi Iwai 			    const char *pfx, int cidx)
1495352f7f91STakashi Iwai {
1496352f7f91STakashi Iwai 	struct nid_path *path;
1497352f7f91STakashi Iwai 	int err;
1498352f7f91STakashi Iwai 
1499196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1500352f7f91STakashi Iwai 	if (!path)
1501352f7f91STakashi Iwai 		return 0;
1502352f7f91STakashi Iwai 	/* bind volume control will be created in the case of dac = 0 */
1503352f7f91STakashi Iwai 	if (dac) {
1504352f7f91STakashi Iwai 		err = add_stereo_vol(codec, pfx, cidx, path);
1505352f7f91STakashi Iwai 		if (err < 0)
1506352f7f91STakashi Iwai 			return err;
1507352f7f91STakashi Iwai 	}
1508352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1509352f7f91STakashi Iwai 	if (err < 0)
1510352f7f91STakashi Iwai 		return err;
1511352f7f91STakashi Iwai 	return 0;
1512352f7f91STakashi Iwai }
1513352f7f91STakashi Iwai 
1514352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1515352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1516352f7f91STakashi Iwai 			     const hda_nid_t *pins, const hda_nid_t *dacs,
1517196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1518352f7f91STakashi Iwai {
1519352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1520352f7f91STakashi Iwai 	struct hda_bind_ctls *ctl;
15215abd4888STakashi Iwai 	char name[44];
1522352f7f91STakashi Iwai 	int i, n, err;
1523352f7f91STakashi Iwai 
1524352f7f91STakashi Iwai 	if (!num_pins || !pins[0])
1525352f7f91STakashi Iwai 		return 0;
1526352f7f91STakashi Iwai 
1527352f7f91STakashi Iwai 	if (num_pins == 1) {
1528352f7f91STakashi Iwai 		hda_nid_t dac = *dacs;
1529352f7f91STakashi Iwai 		if (!dac)
1530352f7f91STakashi Iwai 			dac = spec->multiout.dac_nids[0];
1531196c1766STakashi Iwai 		return create_extra_out(codec, *pins, dac, paths[0], pfx, 0);
1532352f7f91STakashi Iwai 	}
1533352f7f91STakashi Iwai 
1534352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1535352f7f91STakashi Iwai 		hda_nid_t dac;
1536352f7f91STakashi Iwai 		if (dacs[num_pins - 1])
1537352f7f91STakashi Iwai 			dac = dacs[i]; /* with individual volumes */
1538352f7f91STakashi Iwai 		else
1539352f7f91STakashi Iwai 			dac = 0;
1540352f7f91STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
1541196c1766STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, paths[i],
1542352f7f91STakashi Iwai 					       "Bass Speaker", 0);
1543352f7f91STakashi Iwai 		} else if (num_pins >= 3) {
1544352f7f91STakashi Iwai 			snprintf(name, sizeof(name), "%s %s",
1545352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1546196c1766STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, paths[i],
1547196c1766STakashi Iwai 					       name, 0);
1548352f7f91STakashi Iwai 		} else {
1549196c1766STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, paths[i],
1550196c1766STakashi Iwai 					       pfx, i);
1551352f7f91STakashi Iwai 		}
1552352f7f91STakashi Iwai 		if (err < 0)
1553352f7f91STakashi Iwai 			return err;
1554352f7f91STakashi Iwai 	}
1555352f7f91STakashi Iwai 	if (dacs[num_pins - 1])
1556352f7f91STakashi Iwai 		return 0;
1557352f7f91STakashi Iwai 
1558352f7f91STakashi Iwai 	/* Let's create a bind-controls for volumes */
1559352f7f91STakashi Iwai 	ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
1560352f7f91STakashi Iwai 	if (!ctl)
1561352f7f91STakashi Iwai 		return -ENOMEM;
1562352f7f91STakashi Iwai 	n = 0;
1563352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1564352f7f91STakashi Iwai 		hda_nid_t vol;
1565352f7f91STakashi Iwai 		struct nid_path *path;
1566352f7f91STakashi Iwai 		if (!pins[i] || !dacs[i])
1567352f7f91STakashi Iwai 			continue;
1568196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
1569352f7f91STakashi Iwai 		if (!path)
1570352f7f91STakashi Iwai 			continue;
1571352f7f91STakashi Iwai 		vol = look_for_out_vol_nid(codec, path);
1572352f7f91STakashi Iwai 		if (vol)
1573352f7f91STakashi Iwai 			ctl->values[n++] =
1574352f7f91STakashi Iwai 				HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
1575352f7f91STakashi Iwai 	}
1576352f7f91STakashi Iwai 	if (n) {
1577352f7f91STakashi Iwai 		snprintf(name, sizeof(name), "%s Playback Volume", pfx);
1578352f7f91STakashi Iwai 		err = add_control(spec, HDA_CTL_BIND_VOL, name, 0, (long)ctl);
1579352f7f91STakashi Iwai 		if (err < 0)
1580352f7f91STakashi Iwai 			return err;
1581352f7f91STakashi Iwai 	}
1582352f7f91STakashi Iwai 	return 0;
1583352f7f91STakashi Iwai }
1584352f7f91STakashi Iwai 
1585352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1586352f7f91STakashi Iwai {
1587352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1588352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1589352f7f91STakashi Iwai 				 spec->autocfg.hp_pins,
1590352f7f91STakashi Iwai 				 spec->multiout.hp_out_nid,
1591196c1766STakashi Iwai 				 spec->hp_paths,
1592352f7f91STakashi Iwai 				 "Headphone");
1593352f7f91STakashi Iwai }
1594352f7f91STakashi Iwai 
1595352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1596352f7f91STakashi Iwai {
1597352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1598352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1599352f7f91STakashi Iwai 				 spec->autocfg.speaker_pins,
1600352f7f91STakashi Iwai 				 spec->multiout.extra_out_nid,
1601196c1766STakashi Iwai 				 spec->speaker_paths,
1602352f7f91STakashi Iwai 				 "Speaker");
1603352f7f91STakashi Iwai }
1604352f7f91STakashi Iwai 
1605352f7f91STakashi Iwai /*
160638cf6f1aSTakashi Iwai  * independent HP controls
160738cf6f1aSTakashi Iwai  */
160838cf6f1aSTakashi Iwai 
160938cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
161038cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
161138cf6f1aSTakashi Iwai {
161238cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
161338cf6f1aSTakashi Iwai }
161438cf6f1aSTakashi Iwai 
161538cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
161638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
161738cf6f1aSTakashi Iwai {
161838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
161938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
162038cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
162138cf6f1aSTakashi Iwai 	return 0;
162238cf6f1aSTakashi Iwai }
162338cf6f1aSTakashi Iwai 
162438cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
162538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
162638cf6f1aSTakashi Iwai {
162738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
162838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
162938cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
163038cf6f1aSTakashi Iwai 	int ret = 0;
163138cf6f1aSTakashi Iwai 
163238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
163338cf6f1aSTakashi Iwai 	if (spec->active_streams) {
163438cf6f1aSTakashi Iwai 		ret = -EBUSY;
163538cf6f1aSTakashi Iwai 		goto unlock;
163638cf6f1aSTakashi Iwai 	}
163738cf6f1aSTakashi Iwai 
163838cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
163938cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
164038cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
164138cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
164238cf6f1aSTakashi Iwai 		else
164338cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
164438cf6f1aSTakashi Iwai 		ret = 1;
164538cf6f1aSTakashi Iwai 	}
164638cf6f1aSTakashi Iwai  unlock:
164738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
164838cf6f1aSTakashi Iwai 	return ret;
164938cf6f1aSTakashi Iwai }
165038cf6f1aSTakashi Iwai 
165138cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
165238cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
165338cf6f1aSTakashi Iwai 	.name = "Independent HP",
165438cf6f1aSTakashi Iwai 	.info = indep_hp_info,
165538cf6f1aSTakashi Iwai 	.get = indep_hp_get,
165638cf6f1aSTakashi Iwai 	.put = indep_hp_put,
165738cf6f1aSTakashi Iwai };
165838cf6f1aSTakashi Iwai 
165938cf6f1aSTakashi Iwai 
166038cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
166138cf6f1aSTakashi Iwai {
166238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
166338cf6f1aSTakashi Iwai 
166438cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
166538cf6f1aSTakashi Iwai 		return 0;
166638cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
166738cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
166838cf6f1aSTakashi Iwai 		return 0;
166938cf6f1aSTakashi Iwai 	}
167038cf6f1aSTakashi Iwai 
167138cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
167238cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
167338cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
167438cf6f1aSTakashi Iwai 		return -ENOMEM;
167538cf6f1aSTakashi Iwai 	return 0;
167638cf6f1aSTakashi Iwai }
167738cf6f1aSTakashi Iwai 
167838cf6f1aSTakashi Iwai /*
1679352f7f91STakashi Iwai  * channel mode enum control
1680352f7f91STakashi Iwai  */
1681352f7f91STakashi Iwai 
1682352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1683352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1684352f7f91STakashi Iwai {
1685352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1686352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1687352f7f91STakashi Iwai 
1688352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1689352f7f91STakashi Iwai 	uinfo->count = 1;
1690352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1691352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1692352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1693352f7f91STakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch",
1694352f7f91STakashi Iwai 		(uinfo->value.enumerated.item + 1) * 2);
1695352f7f91STakashi Iwai 	return 0;
1696352f7f91STakashi Iwai }
1697352f7f91STakashi Iwai 
1698352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1699352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1700352f7f91STakashi Iwai {
1701352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1702352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1703352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
1704352f7f91STakashi Iwai 	return 0;
1705352f7f91STakashi Iwai }
1706352f7f91STakashi Iwai 
1707196c1766STakashi Iwai static inline struct nid_path *
1708196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1709196c1766STakashi Iwai {
1710196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1711196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1712196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1713196c1766STakashi Iwai }
1714196c1766STakashi Iwai 
1715352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1716352f7f91STakashi Iwai {
1717352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1718352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1719352f7f91STakashi Iwai 	struct nid_path *path;
1720352f7f91STakashi Iwai 
1721196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1722352f7f91STakashi Iwai 	if (!path)
1723352f7f91STakashi Iwai 		return -EINVAL;
1724352f7f91STakashi Iwai 
1725352f7f91STakashi Iwai 	if (path->active == output)
1726352f7f91STakashi Iwai 		return 0;
1727352f7f91STakashi Iwai 
1728352f7f91STakashi Iwai 	if (output) {
1729352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
1730352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1731d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1732352f7f91STakashi Iwai 	} else {
1733d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1734352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
1735352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid,
1736352f7f91STakashi Iwai 					  spec->multi_io[idx].ctl_in);
1737352f7f91STakashi Iwai 	}
1738352f7f91STakashi Iwai 	return 0;
1739352f7f91STakashi Iwai }
1740352f7f91STakashi Iwai 
1741352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1742352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1743352f7f91STakashi Iwai {
1744352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1745352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1746352f7f91STakashi Iwai 	int i, ch;
1747352f7f91STakashi Iwai 
1748352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1749352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1750352f7f91STakashi Iwai 		return -EINVAL;
1751352f7f91STakashi Iwai 	if (ch == (spec->ext_channel_count - 1) / 2)
1752352f7f91STakashi Iwai 		return 0;
1753352f7f91STakashi Iwai 	spec->ext_channel_count = (ch + 1) * 2;
1754352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1755352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1756352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1757352f7f91STakashi Iwai 					  spec->const_channel_count);
1758352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1759352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1760352f7f91STakashi Iwai 	return 1;
1761352f7f91STakashi Iwai }
1762352f7f91STakashi Iwai 
1763352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1764352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1765352f7f91STakashi Iwai 	.name = "Channel Mode",
1766352f7f91STakashi Iwai 	.info = ch_mode_info,
1767352f7f91STakashi Iwai 	.get = ch_mode_get,
1768352f7f91STakashi Iwai 	.put = ch_mode_put,
1769352f7f91STakashi Iwai };
1770352f7f91STakashi Iwai 
1771352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1772352f7f91STakashi Iwai {
1773352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1774352f7f91STakashi Iwai 
1775352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
177612c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1777352f7f91STakashi Iwai 			return -ENOMEM;
1778352f7f91STakashi Iwai 	}
1779352f7f91STakashi Iwai 	return 0;
1780352f7f91STakashi Iwai }
1781352f7f91STakashi Iwai 
1782352f7f91STakashi Iwai /*
1783c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1784c30aa7b2STakashi Iwai  */
1785c30aa7b2STakashi Iwai 
1786c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1787c30aa7b2STakashi Iwai 
1788c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1789c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1790c30aa7b2STakashi Iwai {
1791c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1792c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1793c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1794c30aa7b2STakashi Iwai 	return 0;
1795c30aa7b2STakashi Iwai }
1796c30aa7b2STakashi Iwai 
1797c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1798c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1799c30aa7b2STakashi Iwai {
1800c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1801c30aa7b2STakashi Iwai 
1802c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1803c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1804c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1805c30aa7b2STakashi Iwai 		return;
1806c30aa7b2STakashi Iwai 	if (do_mix) {
1807c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1808c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1809c30aa7b2STakashi Iwai 	} else {
1810c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1811c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1812c30aa7b2STakashi Iwai 	}
1813c30aa7b2STakashi Iwai }
1814c30aa7b2STakashi Iwai 
1815c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1816c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1817c30aa7b2STakashi Iwai {
1818c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1819c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1820c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
1821c30aa7b2STakashi Iwai 
1822c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
1823c30aa7b2STakashi Iwai 		return 0;
1824c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
1825c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
1826c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
1827c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
1828c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
1829c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
1830c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
1831c30aa7b2STakashi Iwai 	return 1;
1832c30aa7b2STakashi Iwai }
1833c30aa7b2STakashi Iwai 
1834c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
1835c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1836c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
1837c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
1838c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
1839c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
1840c30aa7b2STakashi Iwai };
1841c30aa7b2STakashi Iwai 
1842c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
1843c30aa7b2STakashi Iwai {
1844c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1845c30aa7b2STakashi Iwai 
1846c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
1847c30aa7b2STakashi Iwai 		return 0;
1848c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1849c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
1850c30aa7b2STakashi Iwai 		return 0;
1851c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
1852c30aa7b2STakashi Iwai 		return -ENOMEM;
1853c30aa7b2STakashi Iwai 	return 0;
1854c30aa7b2STakashi Iwai }
1855c30aa7b2STakashi Iwai 
1856c30aa7b2STakashi Iwai /*
1857352f7f91STakashi Iwai  * shared headphone/mic handling
1858352f7f91STakashi Iwai  */
1859352f7f91STakashi Iwai 
1860352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
1861352f7f91STakashi Iwai 
1862352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
1863352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
1864352f7f91STakashi Iwai {
1865352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1866352f7f91STakashi Iwai 	unsigned int val;
1867352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
1868352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
1869352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
1870352f7f91STakashi Iwai 	 */
1871352f7f91STakashi Iwai 
1872352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
1873352f7f91STakashi Iwai 
1874352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
1875352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
1876352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
1877352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
1878352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
1879352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
18807594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
18817594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
1882352f7f91STakashi Iwai 	}
1883352f7f91STakashi Iwai 
1884352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
18857594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, val);
1886352f7f91STakashi Iwai 
1887352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
1888352f7f91STakashi Iwai 	call_update_outputs(codec);
1889352f7f91STakashi Iwai }
1890352f7f91STakashi Iwai 
1891352f7f91STakashi Iwai /* create a shared input with the headphone out */
1892352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
1893352f7f91STakashi Iwai {
1894352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1895352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1896352f7f91STakashi Iwai 	unsigned int defcfg;
1897352f7f91STakashi Iwai 	hda_nid_t nid;
1898352f7f91STakashi Iwai 
1899352f7f91STakashi Iwai 	/* only one internal input pin? */
1900352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
1901352f7f91STakashi Iwai 		return 0;
1902352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
1903352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
1904352f7f91STakashi Iwai 		return 0;
1905352f7f91STakashi Iwai 
1906352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1907352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
1908352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
1909352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
1910352f7f91STakashi Iwai 	else
1911352f7f91STakashi Iwai 		return 0; /* both not available */
1912352f7f91STakashi Iwai 
1913352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
1914352f7f91STakashi Iwai 		return 0; /* no input */
1915352f7f91STakashi Iwai 
1916352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
1917352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
1918352f7f91STakashi Iwai 	cfg->num_inputs = 2;
1919352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
1920352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
1921352f7f91STakashi Iwai 	return 0;
1922352f7f91STakashi Iwai }
1923352f7f91STakashi Iwai 
1924352f7f91STakashi Iwai 
1925352f7f91STakashi Iwai /*
1926352f7f91STakashi Iwai  * Parse input paths
1927352f7f91STakashi Iwai  */
1928352f7f91STakashi Iwai 
1929352f7f91STakashi Iwai #ifdef CONFIG_PM
1930352f7f91STakashi Iwai /* add the powersave loopback-list entry */
1931352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
1932352f7f91STakashi Iwai {
1933352f7f91STakashi Iwai 	struct hda_amp_list *list;
1934352f7f91STakashi Iwai 
1935352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
1936352f7f91STakashi Iwai 		return;
1937352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
1938352f7f91STakashi Iwai 	list->nid = mix;
1939352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
1940352f7f91STakashi Iwai 	list->idx = idx;
1941352f7f91STakashi Iwai 	spec->num_loopbacks++;
1942cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
1943cb53c626STakashi Iwai }
1944cb53c626STakashi Iwai #else
1945352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
1946cb53c626STakashi Iwai #endif
1947cb53c626STakashi Iwai 
1948352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
1949196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
1950196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
1951352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
19521da177e4SLinus Torvalds {
1953352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1954352f7f91STakashi Iwai 	struct nid_path *path;
1955352f7f91STakashi Iwai 	unsigned int val;
1956352f7f91STakashi Iwai 	int err, idx;
19571da177e4SLinus Torvalds 
1958352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
1959352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
1960352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
1961352f7f91STakashi Iwai 
19624ac0eefaSTakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, HDA_PARSE_ALL);
1963352f7f91STakashi Iwai 	if (!path)
1964352f7f91STakashi Iwai 		return -EINVAL;
19650c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
1966196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
1967352f7f91STakashi Iwai 
1968352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
1969352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
1970352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1971352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
1972d13bd412STakashi Iwai 		if (err < 0)
19731da177e4SLinus Torvalds 			return err;
1974352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
19751da177e4SLinus Torvalds 	}
19761da177e4SLinus Torvalds 
1977352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
1978352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1979352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
1980d13bd412STakashi Iwai 		if (err < 0)
19811da177e4SLinus Torvalds 			return err;
1982352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
19831da177e4SLinus Torvalds 	}
19841da177e4SLinus Torvalds 
1985352f7f91STakashi Iwai 	path->active = true;
1986352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
1987352f7f91STakashi Iwai 	return 0;
19881da177e4SLinus Torvalds }
19891da177e4SLinus Torvalds 
1990352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
19911da177e4SLinus Torvalds {
1992352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
1993352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
1994352f7f91STakashi Iwai }
1995352f7f91STakashi Iwai 
1996352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
1997352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
1998352f7f91STakashi Iwai {
1999352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2000352f7f91STakashi Iwai 	hda_nid_t nid;
2001352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2002352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2003352f7f91STakashi Iwai 	int i, nums = 0;
2004352f7f91STakashi Iwai 
2005352f7f91STakashi Iwai 	nid = codec->start_nid;
2006352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2007352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2008352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2009352f7f91STakashi Iwai 
2010352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2011352f7f91STakashi Iwai 			continue;
2012352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2013352f7f91STakashi Iwai 		if (++nums >= max_nums)
2014352f7f91STakashi Iwai 			break;
2015352f7f91STakashi Iwai 	}
2016352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
2017352f7f91STakashi Iwai 	return nums;
2018352f7f91STakashi Iwai }
2019352f7f91STakashi Iwai 
2020352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2021352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2022352f7f91STakashi Iwai  */
2023352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2024352f7f91STakashi Iwai {
2025352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2026352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2027352f7f91STakashi Iwai 	hda_nid_t adc_nids[ARRAY_SIZE(spec->adc_nids)];
2028352f7f91STakashi Iwai 	int i, n, nums;
2029352f7f91STakashi Iwai 	hda_nid_t pin, adc;
2030352f7f91STakashi Iwai 
2031352f7f91STakashi Iwai  again:
2032352f7f91STakashi Iwai 	nums = 0;
2033352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2034352f7f91STakashi Iwai 		adc = spec->adc_nids[n];
2035352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2036352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
2037352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
2038352f7f91STakashi Iwai 				break;
2039352f7f91STakashi Iwai 		}
2040352f7f91STakashi Iwai 		if (i >= imux->num_items)
2041352f7f91STakashi Iwai 			adc_nids[nums++] = adc;
2042352f7f91STakashi Iwai 	}
2043352f7f91STakashi Iwai 
2044352f7f91STakashi Iwai 	if (!nums) {
2045352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
2046352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
2047352f7f91STakashi Iwai 			imux->num_items = 1;
2048352f7f91STakashi Iwai 			goto again;
2049352f7f91STakashi Iwai 		}
2050352f7f91STakashi Iwai 
2051352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2052352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2053352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
2054352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
2055352f7f91STakashi Iwai 				adc = spec->adc_nids[n];
2056352f7f91STakashi Iwai 				if (is_reachable_path(codec, pin, adc)) {
2057352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2058352f7f91STakashi Iwai 					break;
2059352f7f91STakashi Iwai 				}
2060352f7f91STakashi Iwai 			}
2061352f7f91STakashi Iwai 		}
2062352f7f91STakashi Iwai 
2063352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2064352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2065352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
2066352f7f91STakashi Iwai 		memcpy(spec->adc_nids, adc_nids, nums * sizeof(hda_nid_t));
2067352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2068352f7f91STakashi Iwai 	}
2069352f7f91STakashi Iwai 
2070352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
2071352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2072352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2073352f7f91STakashi Iwai 	}
2074352f7f91STakashi Iwai 
2075352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2076352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
2077352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
2078352f7f91STakashi Iwai 
20791da177e4SLinus Torvalds 	return 0;
20801da177e4SLinus Torvalds }
20811da177e4SLinus Torvalds 
20821da177e4SLinus Torvalds /*
2083352f7f91STakashi Iwai  * create playback/capture controls for input pins
20841da177e4SLinus Torvalds  */
2085352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2086a7da6ce5STakashi Iwai {
2087352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2088352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2089352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2090352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2091352f7f91STakashi Iwai 	int num_adcs;
2092352f7f91STakashi Iwai 	int i, c, err, type_idx = 0;
2093352f7f91STakashi Iwai 	const char *prev_label = NULL;
2094a7da6ce5STakashi Iwai 
2095352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2096352f7f91STakashi Iwai 	if (num_adcs < 0)
2097352f7f91STakashi Iwai 		return 0;
2098352f7f91STakashi Iwai 
2099352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2100352f7f91STakashi Iwai 		hda_nid_t pin;
2101352f7f91STakashi Iwai 		const char *label;
2102352f7f91STakashi Iwai 		bool imux_added;
2103352f7f91STakashi Iwai 
2104352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2105352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2106352f7f91STakashi Iwai 			continue;
2107352f7f91STakashi Iwai 
2108352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2109352f7f91STakashi Iwai 		if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2110352f7f91STakashi Iwai 			label = "Headphone Mic";
2111352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2112352f7f91STakashi Iwai 			type_idx++;
2113352f7f91STakashi Iwai 		else
2114352f7f91STakashi Iwai 			type_idx = 0;
2115352f7f91STakashi Iwai 		prev_label = label;
2116352f7f91STakashi Iwai 
2117352f7f91STakashi Iwai 		if (mixer) {
2118352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2119196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2120352f7f91STakashi Iwai 						       label, type_idx, mixer);
2121a7da6ce5STakashi Iwai 				if (err < 0)
2122a7da6ce5STakashi Iwai 					return err;
2123a7da6ce5STakashi Iwai 			}
2124352f7f91STakashi Iwai 		}
2125352f7f91STakashi Iwai 
2126352f7f91STakashi Iwai 		imux_added = false;
2127352f7f91STakashi Iwai 		for (c = 0; c < num_adcs; c++) {
2128352f7f91STakashi Iwai 			struct nid_path *path;
2129352f7f91STakashi Iwai 			hda_nid_t adc = spec->adc_nids[c];
2130352f7f91STakashi Iwai 
2131352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
2132352f7f91STakashi Iwai 				continue;
2133352f7f91STakashi Iwai 			path = snd_array_new(&spec->paths);
2134352f7f91STakashi Iwai 			if (!path)
2135352f7f91STakashi Iwai 				return -ENOMEM;
2136352f7f91STakashi Iwai 			memset(path, 0, sizeof(*path));
21374ac0eefaSTakashi Iwai 			if (!snd_hda_parse_nid_path(codec, pin, adc, HDA_PARSE_ALL, path)) {
2138352f7f91STakashi Iwai 				snd_printd(KERN_ERR
2139352f7f91STakashi Iwai 					   "invalid input path 0x%x -> 0x%x\n",
2140352f7f91STakashi Iwai 					   pin, adc);
2141352f7f91STakashi Iwai 				spec->paths.used--;
2142352f7f91STakashi Iwai 				continue;
2143352f7f91STakashi Iwai 			}
21440c8c0f56STakashi Iwai 			print_nid_path("input", path);
2145352f7f91STakashi Iwai 
2146352f7f91STakashi Iwai 			if (!imux_added) {
2147352f7f91STakashi Iwai 				spec->imux_pins[imux->num_items] = pin;
2148352f7f91STakashi Iwai 				snd_hda_add_imux_item(imux, label,
2149352f7f91STakashi Iwai 						      imux->num_items, NULL);
2150352f7f91STakashi Iwai 				imux_added = true;
2151352f7f91STakashi Iwai 			}
2152352f7f91STakashi Iwai 		}
2153352f7f91STakashi Iwai 	}
2154352f7f91STakashi Iwai 
2155a7da6ce5STakashi Iwai 	return 0;
2156a7da6ce5STakashi Iwai }
2157a7da6ce5STakashi Iwai 
21581da177e4SLinus Torvalds 
2159352f7f91STakashi Iwai /*
2160352f7f91STakashi Iwai  * input source mux
2161352f7f91STakashi Iwai  */
2162352f7f91STakashi Iwai 
2163352f7f91STakashi Iwai /* get the ADC NID corresponding to the given index */
2164352f7f91STakashi Iwai static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
2165352f7f91STakashi Iwai {
2166352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2167352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2168352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2169352f7f91STakashi Iwai 	return spec->adc_nids[adc_idx];
217097ec558aSTakashi Iwai }
2171352f7f91STakashi Iwai 
2172352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2173352f7f91STakashi Iwai 		      unsigned int idx);
2174352f7f91STakashi Iwai 
2175352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2176352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2177352f7f91STakashi Iwai {
2178352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2179352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2180352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2181352f7f91STakashi Iwai }
2182352f7f91STakashi Iwai 
2183352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2184352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2185352f7f91STakashi Iwai {
2186352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2187352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2188352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2189352f7f91STakashi Iwai 
2190352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
21911da177e4SLinus Torvalds 	return 0;
21921da177e4SLinus Torvalds }
21931da177e4SLinus Torvalds 
2194352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2195352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
21961da177e4SLinus Torvalds {
2197352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2198352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2199352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2200352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2201352f7f91STakashi Iwai }
2202352f7f91STakashi Iwai 
2203352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
22041da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2205352f7f91STakashi Iwai 	.name = "Input Source",
2206352f7f91STakashi Iwai 	.info = mux_enum_info,
2207352f7f91STakashi Iwai 	.get = mux_enum_get,
2208352f7f91STakashi Iwai 	.put = mux_enum_put,
22091da177e4SLinus Torvalds };
2210071c73adSTakashi Iwai 
221147d46abbSTakashi Iwai /*
221247d46abbSTakashi Iwai  * capture volume and capture switch ctls
221347d46abbSTakashi Iwai  */
221447d46abbSTakashi Iwai 
2215352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2216352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2217071c73adSTakashi Iwai 
221847d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2219352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2220352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2221352f7f91STakashi Iwai 			  put_call_t func, int type)
2222352f7f91STakashi Iwai {
2223352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2224352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2225352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2226352f7f91STakashi Iwai 	struct nid_path *path;
2227352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2228071c73adSTakashi Iwai 
2229352f7f91STakashi Iwai 	imux = &spec->input_mux;
2230352f7f91STakashi Iwai 	adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2231352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
223247d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
223347d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
223447d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
223547d46abbSTakashi Iwai 	 */
2236352f7f91STakashi Iwai 	codec->cached_write = 1;
2237352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2238352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2239352f7f91STakashi Iwai 					    get_adc_nid(codec, adc_idx, i));
2240352f7f91STakashi Iwai 		if (!path->ctls[type])
2241352f7f91STakashi Iwai 			continue;
2242352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2243352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2244352f7f91STakashi Iwai 		if (err < 0)
2245352f7f91STakashi Iwai 			goto error;
2246352f7f91STakashi Iwai 	}
2247352f7f91STakashi Iwai  error:
2248352f7f91STakashi Iwai 	codec->cached_write = 0;
2249352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
225047d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2251352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2252352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
2253352f7f91STakashi Iwai 	return err;
2254352f7f91STakashi Iwai }
2255352f7f91STakashi Iwai 
2256352f7f91STakashi Iwai /* capture volume ctl callbacks */
2257352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2258352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2259352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2260352f7f91STakashi Iwai 
2261352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2262352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2263352f7f91STakashi Iwai {
2264352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2265352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2266352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2267352f7f91STakashi Iwai }
2268352f7f91STakashi Iwai 
2269352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2270352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2271352f7f91STakashi Iwai 	.name = "Capture Volume",
2272352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2273352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2274352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2275352f7f91STakashi Iwai 	.info = cap_vol_info,
2276352f7f91STakashi Iwai 	.get = cap_vol_get,
2277352f7f91STakashi Iwai 	.put = cap_vol_put,
2278352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2279352f7f91STakashi Iwai };
2280352f7f91STakashi Iwai 
2281352f7f91STakashi Iwai /* capture switch ctl callbacks */
2282352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2283352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2284352f7f91STakashi Iwai 
2285352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2286352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2287352f7f91STakashi Iwai {
2288352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2289352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2290352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2291352f7f91STakashi Iwai }
2292352f7f91STakashi Iwai 
2293352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2294352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2295352f7f91STakashi Iwai 	.name = "Capture Switch",
2296352f7f91STakashi Iwai 	.info = cap_sw_info,
2297352f7f91STakashi Iwai 	.get = cap_sw_get,
2298352f7f91STakashi Iwai 	.put = cap_sw_put,
2299352f7f91STakashi Iwai };
2300352f7f91STakashi Iwai 
2301352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2302352f7f91STakashi Iwai {
2303352f7f91STakashi Iwai 	hda_nid_t nid;
2304352f7f91STakashi Iwai 	int i, depth;
2305352f7f91STakashi Iwai 
2306352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2307352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2308352f7f91STakashi Iwai 		if (depth >= path->depth)
2309352f7f91STakashi Iwai 			return -EINVAL;
2310352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2311352f7f91STakashi Iwai 		nid = path->path[i];
2312352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2313352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2314352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2315352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2316352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2317352f7f91STakashi Iwai 				int idx = path->idx[i];
2318352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2319352f7f91STakashi Iwai 					idx = 0;
2320352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2321352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2322352f7f91STakashi Iwai 			}
2323352f7f91STakashi Iwai 		}
2324352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2325352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2326352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2327352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2328352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2329352f7f91STakashi Iwai 				int idx = path->idx[i];
2330352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2331352f7f91STakashi Iwai 					idx = 0;
2332352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2333352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2334352f7f91STakashi Iwai 			}
2335352f7f91STakashi Iwai 		}
2336352f7f91STakashi Iwai 	}
2337352f7f91STakashi Iwai 	return 0;
2338352f7f91STakashi Iwai }
2339352f7f91STakashi Iwai 
2340352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2341352f7f91STakashi Iwai {
2342352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2343352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2344352f7f91STakashi Iwai 	unsigned int val;
2345352f7f91STakashi Iwai 	int i;
2346352f7f91STakashi Iwai 
2347352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2348352f7f91STakashi Iwai 		return false;
2349352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2350352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2351352f7f91STakashi Iwai 			continue;
2352352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2353352f7f91STakashi Iwai 			return false;
2354352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2355352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2356352f7f91STakashi Iwai 	}
2357352f7f91STakashi Iwai 	return false;
2358352f7f91STakashi Iwai }
2359352f7f91STakashi Iwai 
2360352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2361352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2362352f7f91STakashi Iwai 			      bool inv_dmic)
2363352f7f91STakashi Iwai {
2364352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2365352f7f91STakashi Iwai 	char tmpname[44];
2366352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2367352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2368352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2369352f7f91STakashi Iwai 	int err;
2370352f7f91STakashi Iwai 
2371352f7f91STakashi Iwai 	if (!ctl)
2372352f7f91STakashi Iwai 		return 0;
2373352f7f91STakashi Iwai 
2374352f7f91STakashi Iwai 	if (label)
2375352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2376352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2377352f7f91STakashi Iwai 	else
2378352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2379352f7f91STakashi Iwai 			 "Capture %s", sfx);
2380352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2381352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2382352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2383352f7f91STakashi Iwai 		return err;
2384352f7f91STakashi Iwai 
2385352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2386352f7f91STakashi Iwai 	if (label)
2387352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2388352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2389352f7f91STakashi Iwai 	else
2390352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2391352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2392352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2393352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2394352f7f91STakashi Iwai }
2395352f7f91STakashi Iwai 
2396352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2397352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2398352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2399352f7f91STakashi Iwai 				     bool inv_dmic)
2400352f7f91STakashi Iwai {
2401352f7f91STakashi Iwai 	int err;
2402352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2403352f7f91STakashi Iwai 	if (err < 0)
2404352f7f91STakashi Iwai 		return err;
2405352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2406071c73adSTakashi Iwai 	if (err < 0)
2407071c73adSTakashi Iwai 		return err;
2408071c73adSTakashi Iwai 	return 0;
24091da177e4SLinus Torvalds }
2410071c73adSTakashi Iwai 
2411352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2412352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2413352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2414352f7f91STakashi Iwai {
2415352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2416352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2417352f7f91STakashi Iwai 
2418352f7f91STakashi Iwai 	if (vol_ctl) {
241912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2420352f7f91STakashi Iwai 		if (!knew)
2421352f7f91STakashi Iwai 			return -ENOMEM;
2422352f7f91STakashi Iwai 		knew->index = idx;
2423352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2424352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2425352f7f91STakashi Iwai 	}
2426352f7f91STakashi Iwai 	if (sw_ctl) {
242712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2428352f7f91STakashi Iwai 		if (!knew)
2429352f7f91STakashi Iwai 			return -ENOMEM;
2430352f7f91STakashi Iwai 		knew->index = idx;
2431352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2432352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2433352f7f91STakashi Iwai 	}
2434352f7f91STakashi Iwai 	return 0;
2435352f7f91STakashi Iwai }
2436352f7f91STakashi Iwai 
2437352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2438352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2439352f7f91STakashi Iwai {
2440352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2441352f7f91STakashi Iwai 	struct nid_path *path;
2442352f7f91STakashi Iwai 	unsigned int ctl;
2443352f7f91STakashi Iwai 	int i;
2444352f7f91STakashi Iwai 
2445352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2446352f7f91STakashi Iwai 				    get_adc_nid(codec, 0, idx));
2447352f7f91STakashi Iwai 	if (!path)
2448352f7f91STakashi Iwai 		return 0;
2449352f7f91STakashi Iwai 	ctl = path->ctls[type];
2450352f7f91STakashi Iwai 	if (!ctl)
2451352f7f91STakashi Iwai 		return 0;
2452352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2453352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2454352f7f91STakashi Iwai 					    get_adc_nid(codec, 0, i));
2455352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2456352f7f91STakashi Iwai 			return 0;
2457352f7f91STakashi Iwai 	}
2458352f7f91STakashi Iwai 	return ctl;
2459352f7f91STakashi Iwai }
2460352f7f91STakashi Iwai 
2461352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2462352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2463352f7f91STakashi Iwai {
2464352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2465352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2466352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2467352f7f91STakashi Iwai 	const char *prev_label = NULL;
2468352f7f91STakashi Iwai 
2469352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2470352f7f91STakashi Iwai 		const char *label;
2471352f7f91STakashi Iwai 		bool inv_dmic;
2472352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
2473352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2474352f7f91STakashi Iwai 			type_idx++;
2475352f7f91STakashi Iwai 		else
2476352f7f91STakashi Iwai 			type_idx = 0;
2477352f7f91STakashi Iwai 		prev_label = label;
2478352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2479352f7f91STakashi Iwai 
2480352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2481352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2482352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2483352f7f91STakashi Iwai 						 inv_dmic);
2484d13bd412STakashi Iwai 			if (err < 0)
2485071c73adSTakashi Iwai 				return err;
2486352f7f91STakashi Iwai 		}
2487352f7f91STakashi Iwai 	}
2488071c73adSTakashi Iwai 	return 0;
2489352f7f91STakashi Iwai }
2490071c73adSTakashi Iwai 
2491352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2492352f7f91STakashi Iwai {
2493352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2494352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2495352f7f91STakashi Iwai 	int i, n, nums, err;
2496352f7f91STakashi Iwai 
2497352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2498352f7f91STakashi Iwai 		nums = 1;
2499352f7f91STakashi Iwai 	else
2500352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2501352f7f91STakashi Iwai 
2502352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2503352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2504624d914dSTakashi Iwai 		const char *name;
2505624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2506624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2507352f7f91STakashi Iwai 		if (!knew)
2508352f7f91STakashi Iwai 			return -ENOMEM;
2509352f7f91STakashi Iwai 		knew->count = nums;
2510352f7f91STakashi Iwai 	}
2511352f7f91STakashi Iwai 
2512352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2513352f7f91STakashi Iwai 		bool multi = false;
2514352f7f91STakashi Iwai 		bool inv_dmic = false;
2515352f7f91STakashi Iwai 		int vol, sw;
2516352f7f91STakashi Iwai 
2517352f7f91STakashi Iwai 		vol = sw = 0;
2518352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2519352f7f91STakashi Iwai 			struct nid_path *path;
2520352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2521352f7f91STakashi Iwai 						    get_adc_nid(codec, n, i));
2522352f7f91STakashi Iwai 			if (!path)
2523352f7f91STakashi Iwai 				continue;
2524352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2525352f7f91STakashi Iwai 			if (!vol)
2526352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
2527352f7f91STakashi Iwai 			else if (vol != path->ctls[NID_PATH_VOL_CTL])
2528352f7f91STakashi Iwai 				multi = true;
2529352f7f91STakashi Iwai 			if (!sw)
2530352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
2531352f7f91STakashi Iwai 			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
2532352f7f91STakashi Iwai 				multi = true;
2533352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2534352f7f91STakashi Iwai 				inv_dmic = true;
2535352f7f91STakashi Iwai 		}
2536352f7f91STakashi Iwai 
2537352f7f91STakashi Iwai 		if (!multi)
2538352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2539352f7f91STakashi Iwai 							inv_dmic);
2540352f7f91STakashi Iwai 		else if (!spec->multi_cap_vol)
2541352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2542352f7f91STakashi Iwai 		else
2543352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
2544d13bd412STakashi Iwai 		if (err < 0)
2545071c73adSTakashi Iwai 			return err;
2546071c73adSTakashi Iwai 	}
2547071c73adSTakashi Iwai 
25481da177e4SLinus Torvalds 	return 0;
25491da177e4SLinus Torvalds }
25501da177e4SLinus Torvalds 
2551352f7f91STakashi Iwai /*
2552352f7f91STakashi Iwai  * add mic boosts if needed
2553352f7f91STakashi Iwai  */
2554352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
2555352f7f91STakashi Iwai {
2556352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2557352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2558352f7f91STakashi Iwai 	int i, err;
2559352f7f91STakashi Iwai 	int type_idx = 0;
2560352f7f91STakashi Iwai 	hda_nid_t nid;
2561352f7f91STakashi Iwai 	const char *prev_label = NULL;
2562352f7f91STakashi Iwai 
2563352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2564352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
2565352f7f91STakashi Iwai 			break;
2566352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
2567352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
2568352f7f91STakashi Iwai 			const char *label;
25695abd4888STakashi Iwai 			char boost_label[44];
2570352f7f91STakashi Iwai 			struct nid_path *path;
2571352f7f91STakashi Iwai 			unsigned int val;
2572352f7f91STakashi Iwai 
2573352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
2574352f7f91STakashi Iwai 			if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2575352f7f91STakashi Iwai 				label = "Headphone Mic";
2576352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
2577352f7f91STakashi Iwai 				type_idx++;
2578352f7f91STakashi Iwai 			else
2579352f7f91STakashi Iwai 				type_idx = 0;
2580352f7f91STakashi Iwai 			prev_label = label;
2581352f7f91STakashi Iwai 
2582352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
2583352f7f91STakashi Iwai 				 "%s Boost Volume", label);
2584352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
2585352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
2586352f7f91STakashi Iwai 					  boost_label, type_idx, val);
2587352f7f91STakashi Iwai 			if (err < 0)
2588352f7f91STakashi Iwai 				return err;
2589352f7f91STakashi Iwai 
2590352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
2591352f7f91STakashi Iwai 			if (path)
2592352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
2593352f7f91STakashi Iwai 		}
2594352f7f91STakashi Iwai 	}
2595352f7f91STakashi Iwai 	return 0;
2596352f7f91STakashi Iwai }
2597352f7f91STakashi Iwai 
2598352f7f91STakashi Iwai /*
2599352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
2600352f7f91STakashi Iwai  */
2601352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
2602352f7f91STakashi Iwai {
2603352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
26040c8c0f56STakashi Iwai 	struct nid_path *path;
2605352f7f91STakashi Iwai 	int i, nums;
2606352f7f91STakashi Iwai 	hda_nid_t dig_nid;
2607352f7f91STakashi Iwai 
2608352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
2609352f7f91STakashi Iwai 	nums = 0;
2610352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
2611352f7f91STakashi Iwai 		hda_nid_t pin = spec->autocfg.dig_out_pins[i];
2612352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
2613352f7f91STakashi Iwai 		if (!dig_nid)
2614352f7f91STakashi Iwai 			continue;
26154ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, HDA_PARSE_ALL);
26160c8c0f56STakashi Iwai 		if (!path)
2617352f7f91STakashi Iwai 			continue;
26180c8c0f56STakashi Iwai 		print_nid_path("digout", path);
2619e1284af7STakashi Iwai 		path->active = true;
2620196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
2621352f7f91STakashi Iwai 		if (!nums) {
2622352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
2623352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
2624352f7f91STakashi Iwai 		} else {
2625352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2626352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2627352f7f91STakashi Iwai 			break;
2628352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
2629352f7f91STakashi Iwai 		}
2630352f7f91STakashi Iwai 		nums++;
2631352f7f91STakashi Iwai 	}
2632352f7f91STakashi Iwai 
2633352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
2634352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
2635352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2636352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
2637352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2638352f7f91STakashi Iwai 				continue;
2639352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
2640352f7f91STakashi Iwai 				continue;
2641352f7f91STakashi Iwai 			path = snd_hda_add_new_path(codec,
2642352f7f91STakashi Iwai 						    spec->autocfg.dig_in_pin,
26434ac0eefaSTakashi Iwai 						    dig_nid, HDA_PARSE_ALL);
2644352f7f91STakashi Iwai 			if (path) {
26450c8c0f56STakashi Iwai 				print_nid_path("digin", path);
2646352f7f91STakashi Iwai 				path->active = true;
2647352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
26482430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
2649352f7f91STakashi Iwai 				break;
2650352f7f91STakashi Iwai 			}
2651352f7f91STakashi Iwai 		}
2652352f7f91STakashi Iwai 	}
2653352f7f91STakashi Iwai }
2654352f7f91STakashi Iwai 
26551da177e4SLinus Torvalds 
26561da177e4SLinus Torvalds /*
2657352f7f91STakashi Iwai  * input MUX handling
26581da177e4SLinus Torvalds  */
26591da177e4SLinus Torvalds 
2660352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
2661352f7f91STakashi Iwai 
2662352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
2663352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2664352f7f91STakashi Iwai 		      unsigned int idx)
2665352f7f91STakashi Iwai {
2666352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2667352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2668352f7f91STakashi Iwai 	struct nid_path *path;
2669352f7f91STakashi Iwai 
2670352f7f91STakashi Iwai 	imux = &spec->input_mux;
2671352f7f91STakashi Iwai 	if (!imux->num_items)
26721da177e4SLinus Torvalds 		return 0;
26731da177e4SLinus Torvalds 
2674352f7f91STakashi Iwai 	if (idx >= imux->num_items)
2675352f7f91STakashi Iwai 		idx = imux->num_items - 1;
2676352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
2677352f7f91STakashi Iwai 		return 0;
2678352f7f91STakashi Iwai 
2679352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec,
2680352f7f91STakashi Iwai 				    spec->imux_pins[spec->cur_mux[adc_idx]],
2681352f7f91STakashi Iwai 				    spec->adc_nids[adc_idx]);
2682352f7f91STakashi Iwai 	if (!path)
2683352f7f91STakashi Iwai 		return 0;
2684352f7f91STakashi Iwai 	if (path->active)
2685352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
2686352f7f91STakashi Iwai 
2687352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
2688352f7f91STakashi Iwai 
2689352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
2690352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
2691352f7f91STakashi Iwai 
2692352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2693352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
2694352f7f91STakashi Iwai 
2695352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2696352f7f91STakashi Iwai 				    get_adc_nid(codec, adc_idx, idx));
2697352f7f91STakashi Iwai 	if (!path)
2698352f7f91STakashi Iwai 		return 0;
2699352f7f91STakashi Iwai 	if (path->active)
2700352f7f91STakashi Iwai 		return 0;
2701352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
2702352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
2703352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
27041da177e4SLinus Torvalds 	return 1;
27051da177e4SLinus Torvalds }
27061da177e4SLinus Torvalds 
27071da177e4SLinus Torvalds 
27081da177e4SLinus Torvalds /*
2709352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
27101da177e4SLinus Torvalds  */
2711352f7f91STakashi Iwai 
2712352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
2713352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
27141da177e4SLinus Torvalds {
2715352f7f91STakashi Iwai 	int i, present = 0;
27161da177e4SLinus Torvalds 
2717352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2718352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2719352f7f91STakashi Iwai 		if (!nid)
2720352f7f91STakashi Iwai 			break;
2721352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
27221da177e4SLinus Torvalds 	}
2723352f7f91STakashi Iwai 	return present;
27241da177e4SLinus Torvalds }
27251da177e4SLinus Torvalds 
2726352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
2727352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
2728352f7f91STakashi Iwai 			bool mute, bool hp_out)
27291da177e4SLinus Torvalds {
2730352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2731352f7f91STakashi Iwai 	unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
2732352f7f91STakashi Iwai 	int i;
27331da177e4SLinus Torvalds 
2734352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2735352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2736352f7f91STakashi Iwai 		unsigned int val;
2737352f7f91STakashi Iwai 		if (!nid)
2738352f7f91STakashi Iwai 			break;
2739352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
2740352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
2741352f7f91STakashi Iwai 		 */
2742352f7f91STakashi Iwai 		if (spec->keep_vref_in_automute) {
2743352f7f91STakashi Iwai 			val = snd_hda_codec_read(codec, nid, 0,
2744352f7f91STakashi Iwai 					AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2745352f7f91STakashi Iwai 			val &= ~PIN_HP;
2746352f7f91STakashi Iwai 		} else
2747352f7f91STakashi Iwai 			val = 0;
2748352f7f91STakashi Iwai 		val |= pin_bits;
27497594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, val);
2750d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
2751352f7f91STakashi Iwai 	}
2752352f7f91STakashi Iwai }
27531da177e4SLinus Torvalds 
2754352f7f91STakashi Iwai /* Toggle outputs muting */
27555d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
2756352f7f91STakashi Iwai {
2757352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2758352f7f91STakashi Iwai 	int on;
2759352f7f91STakashi Iwai 
2760352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
2761352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
2762352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
2763352f7f91STakashi Iwai 	 */
2764352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
2765352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2766352f7f91STakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute, true);
2767352f7f91STakashi Iwai 
2768352f7f91STakashi Iwai 	if (!spec->automute_speaker)
2769352f7f91STakashi Iwai 		on = 0;
2770352f7f91STakashi Iwai 	else
2771352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
2772352f7f91STakashi Iwai 	on |= spec->master_mute;
2773352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
2774352f7f91STakashi Iwai 		    spec->autocfg.speaker_pins, on, false);
2775352f7f91STakashi Iwai 
2776352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
2777352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
2778352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
2779352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
2780352f7f91STakashi Iwai 		return;
2781352f7f91STakashi Iwai 	if (!spec->automute_lo)
2782352f7f91STakashi Iwai 		on = 0;
2783352f7f91STakashi Iwai 	else
2784352f7f91STakashi Iwai 		on = spec->hp_jack_present;
2785352f7f91STakashi Iwai 	on |= spec->master_mute;
2786352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2787352f7f91STakashi Iwai 		    spec->autocfg.line_out_pins, on, false);
2788352f7f91STakashi Iwai }
27895d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
2790352f7f91STakashi Iwai 
2791352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
2792352f7f91STakashi Iwai {
2793352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2794352f7f91STakashi Iwai 	if (spec->automute_hook)
2795352f7f91STakashi Iwai 		spec->automute_hook(codec);
2796352f7f91STakashi Iwai 	else
27975d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
2798352f7f91STakashi Iwai }
2799352f7f91STakashi Iwai 
2800352f7f91STakashi Iwai /* standard HP-automute helper */
28015d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2802352f7f91STakashi Iwai {
2803352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2804352f7f91STakashi Iwai 
2805352f7f91STakashi Iwai 	spec->hp_jack_present =
2806352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2807352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
2808352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
2809352f7f91STakashi Iwai 		return;
2810352f7f91STakashi Iwai 	call_update_outputs(codec);
2811352f7f91STakashi Iwai }
28125d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
2813352f7f91STakashi Iwai 
2814352f7f91STakashi Iwai /* standard line-out-automute helper */
28155d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2816352f7f91STakashi Iwai {
2817352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2818352f7f91STakashi Iwai 
2819352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
2820352f7f91STakashi Iwai 		return;
2821352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
2822352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
2823352f7f91STakashi Iwai 		return;
2824352f7f91STakashi Iwai 
2825352f7f91STakashi Iwai 	spec->line_jack_present =
2826352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2827352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
2828352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
2829352f7f91STakashi Iwai 		return;
2830352f7f91STakashi Iwai 	call_update_outputs(codec);
2831352f7f91STakashi Iwai }
28325d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
2833352f7f91STakashi Iwai 
2834352f7f91STakashi Iwai /* standard mic auto-switch helper */
28355d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
2836352f7f91STakashi Iwai {
2837352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2838352f7f91STakashi Iwai 	int i;
2839352f7f91STakashi Iwai 
2840352f7f91STakashi Iwai 	if (!spec->auto_mic)
2841352f7f91STakashi Iwai 		return;
2842352f7f91STakashi Iwai 
2843352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
2844352f7f91STakashi Iwai 		if (snd_hda_jack_detect(codec, spec->am_entry[i].pin)) {
2845352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
2846352f7f91STakashi Iwai 			return;
2847352f7f91STakashi Iwai 		}
2848352f7f91STakashi Iwai 	}
2849352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
28501da177e4SLinus Torvalds }
28515d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
28521da177e4SLinus Torvalds 
28531da177e4SLinus Torvalds /*
2854352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
28551da177e4SLinus Torvalds  */
2856352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
2857352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2858352f7f91STakashi Iwai {
2859352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2860352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2861352f7f91STakashi Iwai 	static const char * const texts3[] = {
2862352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
28631da177e4SLinus Torvalds 	};
28641da177e4SLinus Torvalds 
2865352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
2866352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
2867352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
2868352f7f91STakashi Iwai }
2869352f7f91STakashi Iwai 
2870352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
2871352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2872352f7f91STakashi Iwai {
2873352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2874352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2875352f7f91STakashi Iwai 	unsigned int val = 0;
2876352f7f91STakashi Iwai 	if (spec->automute_speaker)
2877352f7f91STakashi Iwai 		val++;
2878352f7f91STakashi Iwai 	if (spec->automute_lo)
2879352f7f91STakashi Iwai 		val++;
2880352f7f91STakashi Iwai 
2881352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
2882352f7f91STakashi Iwai 	return 0;
2883352f7f91STakashi Iwai }
2884352f7f91STakashi Iwai 
2885352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
2886352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2887352f7f91STakashi Iwai {
2888352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2889352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2890352f7f91STakashi Iwai 
2891352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
2892352f7f91STakashi Iwai 	case 0:
2893352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
2894352f7f91STakashi Iwai 			return 0;
2895352f7f91STakashi Iwai 		spec->automute_speaker = 0;
2896352f7f91STakashi Iwai 		spec->automute_lo = 0;
2897352f7f91STakashi Iwai 		break;
2898352f7f91STakashi Iwai 	case 1:
2899352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
2900352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
2901352f7f91STakashi Iwai 				return 0;
2902352f7f91STakashi Iwai 			spec->automute_speaker = 1;
2903352f7f91STakashi Iwai 			spec->automute_lo = 0;
2904352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
2905352f7f91STakashi Iwai 			if (spec->automute_lo)
2906352f7f91STakashi Iwai 				return 0;
2907352f7f91STakashi Iwai 			spec->automute_lo = 1;
2908352f7f91STakashi Iwai 		} else
2909352f7f91STakashi Iwai 			return -EINVAL;
2910352f7f91STakashi Iwai 		break;
2911352f7f91STakashi Iwai 	case 2:
2912352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
2913352f7f91STakashi Iwai 			return -EINVAL;
2914352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
2915352f7f91STakashi Iwai 			return 0;
2916352f7f91STakashi Iwai 		spec->automute_speaker = 1;
2917352f7f91STakashi Iwai 		spec->automute_lo = 1;
2918352f7f91STakashi Iwai 		break;
2919352f7f91STakashi Iwai 	default:
2920352f7f91STakashi Iwai 		return -EINVAL;
2921352f7f91STakashi Iwai 	}
2922352f7f91STakashi Iwai 	call_update_outputs(codec);
2923352f7f91STakashi Iwai 	return 1;
2924352f7f91STakashi Iwai }
2925352f7f91STakashi Iwai 
2926352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
2927352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2928352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
2929352f7f91STakashi Iwai 	.info = automute_mode_info,
2930352f7f91STakashi Iwai 	.get = automute_mode_get,
2931352f7f91STakashi Iwai 	.put = automute_mode_put,
2932352f7f91STakashi Iwai };
2933352f7f91STakashi Iwai 
2934352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
2935352f7f91STakashi Iwai {
2936352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2937352f7f91STakashi Iwai 
293812c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
2939352f7f91STakashi Iwai 		return -ENOMEM;
2940352f7f91STakashi Iwai 	return 0;
2941352f7f91STakashi Iwai }
2942352f7f91STakashi Iwai 
2943352f7f91STakashi Iwai /*
2944352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
2945352f7f91STakashi Iwai  * Set up appropriately if really supported
2946352f7f91STakashi Iwai  */
2947352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
2948352f7f91STakashi Iwai {
2949352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2950352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2951352f7f91STakashi Iwai 	int present = 0;
2952352f7f91STakashi Iwai 	int i, err;
2953352f7f91STakashi Iwai 
2954352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
2955352f7f91STakashi Iwai 		present++;
2956352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
2957352f7f91STakashi Iwai 		present++;
2958352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
2959352f7f91STakashi Iwai 		present++;
2960352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
2961352f7f91STakashi Iwai 		return 0;
2962352f7f91STakashi Iwai 
2963352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
2964352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2965352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2966352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2967352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2968352f7f91STakashi Iwai 	}
2969352f7f91STakashi Iwai 
2970352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
2971352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2972352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
2973352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
2974352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
2975352f7f91STakashi Iwai 	}
2976352f7f91STakashi Iwai 
2977352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
2978352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
2979352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
2980352f7f91STakashi Iwai 			continue;
2981352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
2982352f7f91STakashi Iwai 			    nid);
2983352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
29842e03e952STakashi Iwai 						    spec->hp_automute_hook ?
29852e03e952STakashi Iwai 						    spec->hp_automute_hook :
29865d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
2987352f7f91STakashi Iwai 		spec->detect_hp = 1;
2988352f7f91STakashi Iwai 	}
2989352f7f91STakashi Iwai 
2990352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
2991352f7f91STakashi Iwai 		if (cfg->speaker_outs)
2992352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
2993352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
2994352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
2995352f7f91STakashi Iwai 					continue;
2996352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
2997352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
2998352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
29992e03e952STakashi Iwai 								    spec->line_automute_hook ?
30002e03e952STakashi Iwai 								    spec->line_automute_hook :
30015d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
3002352f7f91STakashi Iwai 				spec->detect_lo = 1;
3003352f7f91STakashi Iwai 			}
3004352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
3005352f7f91STakashi Iwai 	}
3006352f7f91STakashi Iwai 
3007352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
3008352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
3009352f7f91STakashi Iwai 
3010352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
3011352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
3012352f7f91STakashi Iwai 
3013352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
3014352f7f91STakashi Iwai 		/* create a control for automute mode */
3015352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
3016352f7f91STakashi Iwai 		if (err < 0)
3017352f7f91STakashi Iwai 			return err;
3018352f7f91STakashi Iwai 	}
3019352f7f91STakashi Iwai 	return 0;
3020352f7f91STakashi Iwai }
3021352f7f91STakashi Iwai 
3022352f7f91STakashi Iwai /* return the position of NID in the list, or -1 if not found */
3023352f7f91STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
3024352f7f91STakashi Iwai {
3025352f7f91STakashi Iwai 	int i;
3026352f7f91STakashi Iwai 	for (i = 0; i < nums; i++)
3027352f7f91STakashi Iwai 		if (list[i] == nid)
3028352f7f91STakashi Iwai 			return i;
3029352f7f91STakashi Iwai 	return -1;
3030352f7f91STakashi Iwai }
3031352f7f91STakashi Iwai 
3032352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
3033352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
3034352f7f91STakashi Iwai {
3035352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3036352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3037352f7f91STakashi Iwai 	int i;
3038352f7f91STakashi Iwai 
3039352f7f91STakashi Iwai 	imux = &spec->input_mux;
3040352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
3041352f7f91STakashi Iwai 		spec->am_entry[i].idx =
3042352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
3043352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
3044352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
3045352f7f91STakashi Iwai 			return false; /* no corresponding imux */
3046352f7f91STakashi Iwai 	}
3047352f7f91STakashi Iwai 
3048352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
3049352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
3050352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
3051352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
3052352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
30532e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
30542e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
30555d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
3056352f7f91STakashi Iwai 	return true;
3057352f7f91STakashi Iwai }
3058352f7f91STakashi Iwai 
3059352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
3060352f7f91STakashi Iwai {
3061352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
3062352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
3063352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
3064352f7f91STakashi Iwai }
3065352f7f91STakashi Iwai 
3066352f7f91STakashi Iwai /*
3067352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
3068352f7f91STakashi Iwai  * Set up if really supported
3069352f7f91STakashi Iwai  */
3070352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
3071352f7f91STakashi Iwai {
3072352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3073352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3074352f7f91STakashi Iwai 	unsigned int types;
3075352f7f91STakashi Iwai 	int i, num_pins;
3076352f7f91STakashi Iwai 
3077352f7f91STakashi Iwai 	types = 0;
3078352f7f91STakashi Iwai 	num_pins = 0;
3079352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3080352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3081352f7f91STakashi Iwai 		unsigned int attr;
3082352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3083352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3084352f7f91STakashi Iwai 		if (types & (1 << attr))
3085352f7f91STakashi Iwai 			return 0; /* already occupied */
3086352f7f91STakashi Iwai 		switch (attr) {
3087352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3088352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3089352f7f91STakashi Iwai 				return 0; /* invalid type */
3090352f7f91STakashi Iwai 			break;
3091352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3092352f7f91STakashi Iwai 			return 0; /* invalid entry */
3093352f7f91STakashi Iwai 		default:
3094352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3095352f7f91STakashi Iwai 				return 0; /* invalid type */
3096352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3097352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3098352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3099352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3100352f7f91STakashi Iwai 				return 0; /* no unsol support */
3101352f7f91STakashi Iwai 			break;
3102352f7f91STakashi Iwai 		}
3103352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3104352f7f91STakashi Iwai 			return 0;
3105352f7f91STakashi Iwai 		types |= (1 << attr);
3106352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3107352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3108352f7f91STakashi Iwai 		num_pins++;
3109352f7f91STakashi Iwai 	}
3110352f7f91STakashi Iwai 
3111352f7f91STakashi Iwai 	if (num_pins < 2)
3112352f7f91STakashi Iwai 		return 0;
3113352f7f91STakashi Iwai 
3114352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3115352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3116352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3117352f7f91STakashi Iwai 	 */
3118352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3119352f7f91STakashi Iwai 	     compare_attr, NULL);
3120352f7f91STakashi Iwai 
3121352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3122352f7f91STakashi Iwai 		return 0;
3123352f7f91STakashi Iwai 
3124352f7f91STakashi Iwai 	spec->auto_mic = 1;
3125352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3126352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3127352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3128352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3129352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3130352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3131352f7f91STakashi Iwai 
3132352f7f91STakashi Iwai 	return 0;
3133352f7f91STakashi Iwai }
3134352f7f91STakashi Iwai 
3135352f7f91STakashi Iwai 
31369eb413e5STakashi Iwai /*
31379eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
31389eb413e5STakashi Iwai  *
31399eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3140352f7f91STakashi Iwai  * or a negative error code
3141352f7f91STakashi Iwai  */
3142352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
31439eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3144352f7f91STakashi Iwai {
3145352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3146352f7f91STakashi Iwai 	int err;
3147352f7f91STakashi Iwai 
31489eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
31499eb413e5STakashi Iwai 		spec->autocfg = *cfg;
31509eb413e5STakashi Iwai 		cfg = &spec->autocfg;
31519eb413e5STakashi Iwai 	}
31529eb413e5STakashi Iwai 
3153352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3154352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3155352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3156352f7f91STakashi Iwai 			spec->no_analog = 1;
3157352f7f91STakashi Iwai 			goto dig_only;
3158352f7f91STakashi Iwai 		}
3159352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3160352f7f91STakashi Iwai 	}
3161352f7f91STakashi Iwai 
3162352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3163352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3164352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3165352f7f91STakashi Iwai 		/* use HP as primary out */
3166352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3167352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3168352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3169352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3170352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3171352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3172352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3173352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3174352f7f91STakashi Iwai 	}
3175352f7f91STakashi Iwai 
3176352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3177352f7f91STakashi Iwai 	if (err < 0)
3178352f7f91STakashi Iwai 		return err;
3179352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3180352f7f91STakashi Iwai 	if (err < 0)
3181352f7f91STakashi Iwai 		return err;
3182352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3183352f7f91STakashi Iwai 	if (err < 0)
3184352f7f91STakashi Iwai 		return err;
3185352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3186352f7f91STakashi Iwai 	if (err < 0)
3187352f7f91STakashi Iwai 		return err;
3188352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3189352f7f91STakashi Iwai 	if (err < 0)
3190352f7f91STakashi Iwai 		return err;
319138cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
319238cf6f1aSTakashi Iwai 	if (err < 0)
319338cf6f1aSTakashi Iwai 		return err;
3194c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3195c30aa7b2STakashi Iwai 	if (err < 0)
3196c30aa7b2STakashi Iwai 		return err;
3197352f7f91STakashi Iwai 	err = create_shared_input(codec);
3198352f7f91STakashi Iwai 	if (err < 0)
3199352f7f91STakashi Iwai 		return err;
3200352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3201352f7f91STakashi Iwai 	if (err < 0)
3202352f7f91STakashi Iwai 		return err;
3203352f7f91STakashi Iwai 
3204352f7f91STakashi Iwai 	/* check the multiple speaker pins */
3205352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
3206352f7f91STakashi Iwai 		spec->const_channel_count = cfg->line_outs * 2;
3207352f7f91STakashi Iwai 	else
3208352f7f91STakashi Iwai 		spec->const_channel_count = cfg->speaker_outs * 2;
3209352f7f91STakashi Iwai 
3210352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
3211352f7f91STakashi Iwai 		spec->multiout.max_channels = max(spec->ext_channel_count,
3212352f7f91STakashi Iwai 						  spec->const_channel_count);
3213352f7f91STakashi Iwai 	else
3214352f7f91STakashi Iwai 		spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3215352f7f91STakashi Iwai 
3216352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3217352f7f91STakashi Iwai 	if (err < 0)
3218352f7f91STakashi Iwai 		return err;
3219352f7f91STakashi Iwai 
3220352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3221352f7f91STakashi Iwai 	if (err < 0)
3222352f7f91STakashi Iwai 		return err;
3223352f7f91STakashi Iwai 
3224352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3225352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3226352f7f91STakashi Iwai 		if (err < 0)
3227352f7f91STakashi Iwai 			return err;
3228352f7f91STakashi Iwai 	}
3229352f7f91STakashi Iwai 
3230352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3231352f7f91STakashi Iwai 	if (err < 0)
3232352f7f91STakashi Iwai 		return err;
3233352f7f91STakashi Iwai 
3234352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3235352f7f91STakashi Iwai 	if (err < 0)
3236352f7f91STakashi Iwai 		return err;
3237352f7f91STakashi Iwai 
3238352f7f91STakashi Iwai  dig_only:
3239352f7f91STakashi Iwai 	parse_digital(codec);
3240352f7f91STakashi Iwai 
3241352f7f91STakashi Iwai 	return 1;
3242352f7f91STakashi Iwai }
3243352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3244352f7f91STakashi Iwai 
3245352f7f91STakashi Iwai 
3246352f7f91STakashi Iwai /*
3247352f7f91STakashi Iwai  * Build control elements
3248352f7f91STakashi Iwai  */
3249352f7f91STakashi Iwai 
3250352f7f91STakashi Iwai /* slave controls for virtual master */
3251352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3252352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3253352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3254352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3255ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3256ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3257ee79c69aSTakashi Iwai 	"Headphone Side",
3258352f7f91STakashi Iwai 	NULL,
3259352f7f91STakashi Iwai };
3260352f7f91STakashi Iwai 
3261352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3262352f7f91STakashi Iwai {
3263352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3264352f7f91STakashi Iwai 	int err;
3265352f7f91STakashi Iwai 
326636502d02STakashi Iwai 	if (spec->kctls.used) {
3267352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3268352f7f91STakashi Iwai 		if (err < 0)
3269352f7f91STakashi Iwai 			return err;
327036502d02STakashi Iwai 	}
3271352f7f91STakashi Iwai 
3272352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3273352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3274352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3275352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3276352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3277352f7f91STakashi Iwai 		if (err < 0)
3278352f7f91STakashi Iwai 			return err;
3279352f7f91STakashi Iwai 		if (!spec->no_analog) {
3280352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3281352f7f91STakashi Iwai 							    &spec->multiout);
3282352f7f91STakashi Iwai 			if (err < 0)
3283352f7f91STakashi Iwai 				return err;
3284352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3285352f7f91STakashi Iwai 		}
3286352f7f91STakashi Iwai 	}
3287352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3288352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3289352f7f91STakashi Iwai 		if (err < 0)
3290352f7f91STakashi Iwai 			return err;
3291352f7f91STakashi Iwai 	}
3292352f7f91STakashi Iwai 
3293352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3294352f7f91STakashi Iwai 	if (!spec->no_analog &&
3295352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3296352f7f91STakashi Iwai 		unsigned int vmaster_tlv[4];
3297352f7f91STakashi Iwai 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
3298352f7f91STakashi Iwai 					HDA_OUTPUT, vmaster_tlv);
3299352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
3300352f7f91STakashi Iwai 					  vmaster_tlv, slave_pfxs,
3301352f7f91STakashi Iwai 					  "Playback Volume");
3302352f7f91STakashi Iwai 		if (err < 0)
3303352f7f91STakashi Iwai 			return err;
3304352f7f91STakashi Iwai 	}
3305352f7f91STakashi Iwai 	if (!spec->no_analog &&
3306352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3307352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3308352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3309352f7f91STakashi Iwai 					    "Playback Switch",
3310352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3311352f7f91STakashi Iwai 		if (err < 0)
3312352f7f91STakashi Iwai 			return err;
3313352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3314fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3315fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3316352f7f91STakashi Iwai 	}
3317352f7f91STakashi Iwai 
3318352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3319352f7f91STakashi Iwai 
3320352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3321352f7f91STakashi Iwai 		int err;
3322352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3323352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3324352f7f91STakashi Iwai 		if (err < 0)
3325352f7f91STakashi Iwai 			return err;
3326352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3327352f7f91STakashi Iwai 		if (err < 0)
3328352f7f91STakashi Iwai 			return err;
3329352f7f91STakashi Iwai 	}
3330352f7f91STakashi Iwai 
3331352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3332352f7f91STakashi Iwai 	if (err < 0)
3333352f7f91STakashi Iwai 		return err;
3334352f7f91STakashi Iwai 
3335352f7f91STakashi Iwai 	return 0;
3336352f7f91STakashi Iwai }
3337352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3338352f7f91STakashi Iwai 
3339352f7f91STakashi Iwai 
3340352f7f91STakashi Iwai /*
3341352f7f91STakashi Iwai  * PCM definitions
3342352f7f91STakashi Iwai  */
3343352f7f91STakashi Iwai 
3344352f7f91STakashi Iwai /*
3345352f7f91STakashi Iwai  * Analog playback callbacks
3346352f7f91STakashi Iwai  */
3347352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3348352f7f91STakashi Iwai 			     struct hda_codec *codec,
3349352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3350352f7f91STakashi Iwai {
3351352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
335238cf6f1aSTakashi Iwai 	int err;
335338cf6f1aSTakashi Iwai 
335438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
335538cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
335638cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3357352f7f91STakashi Iwai 					     hinfo);
335838cf6f1aSTakashi Iwai 	if (!err)
335938cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
336038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
336138cf6f1aSTakashi Iwai 	return err;
3362352f7f91STakashi Iwai }
3363352f7f91STakashi Iwai 
3364352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
336597ec558aSTakashi Iwai 				struct hda_codec *codec,
336697ec558aSTakashi Iwai 				unsigned int stream_tag,
336797ec558aSTakashi Iwai 				unsigned int format,
336897ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
336997ec558aSTakashi Iwai {
3370352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3371352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3372352f7f91STakashi Iwai 						stream_tag, format, substream);
3373352f7f91STakashi Iwai }
337497ec558aSTakashi Iwai 
3375352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3376352f7f91STakashi Iwai 				struct hda_codec *codec,
3377352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3378352f7f91STakashi Iwai {
3379352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3380352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3381352f7f91STakashi Iwai }
3382352f7f91STakashi Iwai 
338338cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
338438cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
338538cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
338638cf6f1aSTakashi Iwai {
338738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
338838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
338938cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
339038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
339138cf6f1aSTakashi Iwai 	return 0;
339238cf6f1aSTakashi Iwai }
339338cf6f1aSTakashi Iwai 
339438cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
339538cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
339638cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
339738cf6f1aSTakashi Iwai {
339838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
339938cf6f1aSTakashi Iwai 	int err = 0;
340038cf6f1aSTakashi Iwai 
340138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
340238cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
340338cf6f1aSTakashi Iwai 		err = -EBUSY;
340438cf6f1aSTakashi Iwai 	else
340538cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
340638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
340738cf6f1aSTakashi Iwai 	return err;
340838cf6f1aSTakashi Iwai }
340938cf6f1aSTakashi Iwai 
341038cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
341138cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
341238cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
341338cf6f1aSTakashi Iwai {
341438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
341538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
341638cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
341738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
341838cf6f1aSTakashi Iwai 	return 0;
341938cf6f1aSTakashi Iwai }
342038cf6f1aSTakashi Iwai 
3421352f7f91STakashi Iwai /*
3422352f7f91STakashi Iwai  * Digital out
3423352f7f91STakashi Iwai  */
3424352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3425352f7f91STakashi Iwai 				 struct hda_codec *codec,
3426352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
3427352f7f91STakashi Iwai {
3428352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3429352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3430352f7f91STakashi Iwai }
3431352f7f91STakashi Iwai 
3432352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3433352f7f91STakashi Iwai 				    struct hda_codec *codec,
3434352f7f91STakashi Iwai 				    unsigned int stream_tag,
3435352f7f91STakashi Iwai 				    unsigned int format,
3436352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3437352f7f91STakashi Iwai {
3438352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3439352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3440352f7f91STakashi Iwai 					     stream_tag, format, substream);
3441352f7f91STakashi Iwai }
3442352f7f91STakashi Iwai 
3443352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3444352f7f91STakashi Iwai 				    struct hda_codec *codec,
3445352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3446352f7f91STakashi Iwai {
3447352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3448352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3449352f7f91STakashi Iwai }
3450352f7f91STakashi Iwai 
3451352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3452352f7f91STakashi Iwai 				  struct hda_codec *codec,
3453352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
3454352f7f91STakashi Iwai {
3455352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3456352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3457352f7f91STakashi Iwai }
3458352f7f91STakashi Iwai 
3459352f7f91STakashi Iwai /*
3460352f7f91STakashi Iwai  * Analog capture
3461352f7f91STakashi Iwai  */
3462352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3463352f7f91STakashi Iwai 				   struct hda_codec *codec,
3464352f7f91STakashi Iwai 				   unsigned int stream_tag,
3465352f7f91STakashi Iwai 				   unsigned int format,
3466352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
3467352f7f91STakashi Iwai {
3468352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3469352f7f91STakashi Iwai 
3470352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
347197ec558aSTakashi Iwai 				   stream_tag, 0, format);
347297ec558aSTakashi Iwai 	return 0;
347397ec558aSTakashi Iwai }
347497ec558aSTakashi Iwai 
3475352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
347697ec558aSTakashi Iwai 				   struct hda_codec *codec,
347797ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
347897ec558aSTakashi Iwai {
3479352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
348097ec558aSTakashi Iwai 
3481352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
3482352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
348397ec558aSTakashi Iwai 	return 0;
348497ec558aSTakashi Iwai }
348597ec558aSTakashi Iwai 
3486352f7f91STakashi Iwai /*
3487352f7f91STakashi Iwai  */
3488352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
3489352f7f91STakashi Iwai 	.substreams = 1,
3490352f7f91STakashi Iwai 	.channels_min = 2,
3491352f7f91STakashi Iwai 	.channels_max = 8,
3492352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3493352f7f91STakashi Iwai 	.ops = {
3494352f7f91STakashi Iwai 		.open = playback_pcm_open,
349538cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
3496352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
3497352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
3498352f7f91STakashi Iwai 	},
3499352f7f91STakashi Iwai };
3500352f7f91STakashi Iwai 
3501352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
3502352f7f91STakashi Iwai 	.substreams = 1,
3503352f7f91STakashi Iwai 	.channels_min = 2,
3504352f7f91STakashi Iwai 	.channels_max = 2,
3505352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3506352f7f91STakashi Iwai };
3507352f7f91STakashi Iwai 
3508352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
3509352f7f91STakashi Iwai 	.substreams = 1,
3510352f7f91STakashi Iwai 	.channels_min = 2,
3511352f7f91STakashi Iwai 	.channels_max = 2,
3512352f7f91STakashi Iwai 	/* NID is set in build_pcms */
351338cf6f1aSTakashi Iwai 	.ops = {
351438cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
351538cf6f1aSTakashi Iwai 		.close = alt_playback_pcm_close
351638cf6f1aSTakashi Iwai 	},
3517352f7f91STakashi Iwai };
3518352f7f91STakashi Iwai 
3519352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
3520352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
3521352f7f91STakashi Iwai 	.channels_min = 2,
3522352f7f91STakashi Iwai 	.channels_max = 2,
3523352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3524352f7f91STakashi Iwai 	.ops = {
3525352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
3526352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
3527352f7f91STakashi Iwai 	},
3528352f7f91STakashi Iwai };
3529352f7f91STakashi Iwai 
3530352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
3531352f7f91STakashi Iwai 	.substreams = 1,
3532352f7f91STakashi Iwai 	.channels_min = 2,
3533352f7f91STakashi Iwai 	.channels_max = 2,
3534352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3535352f7f91STakashi Iwai 	.ops = {
3536352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
3537352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
3538352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
3539352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
3540352f7f91STakashi Iwai 	},
3541352f7f91STakashi Iwai };
3542352f7f91STakashi Iwai 
3543352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
3544352f7f91STakashi Iwai 	.substreams = 1,
3545352f7f91STakashi Iwai 	.channels_min = 2,
3546352f7f91STakashi Iwai 	.channels_max = 2,
3547352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3548352f7f91STakashi Iwai };
3549352f7f91STakashi Iwai 
3550352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
3551352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
3552352f7f91STakashi Iwai 	.substreams = 0,
3553352f7f91STakashi Iwai 	.channels_min = 0,
3554352f7f91STakashi Iwai 	.channels_max = 0,
3555352f7f91STakashi Iwai };
3556352f7f91STakashi Iwai 
3557352f7f91STakashi Iwai /*
3558352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
3559352f7f91STakashi Iwai  */
3560352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
35611da177e4SLinus Torvalds {
3562352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3563352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
35641da177e4SLinus Torvalds 
3565352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
3566352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
3567352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3568352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
3569352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
3570352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
3571352f7f91STakashi Iwai 					   spec->cur_adc_format);
3572352f7f91STakashi Iwai 		return true;
3573352f7f91STakashi Iwai 	}
3574352f7f91STakashi Iwai 	return false;
3575352f7f91STakashi Iwai }
3576352f7f91STakashi Iwai 
3577352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
3578352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3579352f7f91STakashi Iwai 				       struct hda_codec *codec,
3580352f7f91STakashi Iwai 				       unsigned int stream_tag,
3581352f7f91STakashi Iwai 				       unsigned int format,
3582352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3583352f7f91STakashi Iwai {
3584352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3585352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
3586352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
3587352f7f91STakashi Iwai 	spec->cur_adc_format = format;
3588352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
35891da177e4SLinus Torvalds 	return 0;
35901da177e4SLinus Torvalds }
35911da177e4SLinus Torvalds 
3592352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3593352f7f91STakashi Iwai 				       struct hda_codec *codec,
3594352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3595352f7f91STakashi Iwai {
3596352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3597352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3598352f7f91STakashi Iwai 	spec->cur_adc = 0;
3599352f7f91STakashi Iwai 	return 0;
3600352f7f91STakashi Iwai }
3601352f7f91STakashi Iwai 
3602352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
3603352f7f91STakashi Iwai 	.substreams = 1,
3604352f7f91STakashi Iwai 	.channels_min = 2,
3605352f7f91STakashi Iwai 	.channels_max = 2,
3606352f7f91STakashi Iwai 	.nid = 0, /* fill later */
3607352f7f91STakashi Iwai 	.ops = {
3608352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
3609352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
3610352f7f91STakashi Iwai 	},
3611352f7f91STakashi Iwai };
3612352f7f91STakashi Iwai 
3613f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
3614f873e536STakashi Iwai 				 const char *chip_name)
3615f873e536STakashi Iwai {
3616f873e536STakashi Iwai 	char *p;
3617f873e536STakashi Iwai 
3618f873e536STakashi Iwai 	if (*str)
3619f873e536STakashi Iwai 		return;
3620f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
3621f873e536STakashi Iwai 
3622f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
3623f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
3624f873e536STakashi Iwai 		if (!isalnum(p[1])) {
3625f873e536STakashi Iwai 			*p = 0;
3626f873e536STakashi Iwai 			break;
3627f873e536STakashi Iwai 		}
3628f873e536STakashi Iwai 	}
3629f873e536STakashi Iwai 	strlcat(str, sfx, len);
3630f873e536STakashi Iwai }
3631f873e536STakashi Iwai 
3632352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
3633352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
3634352f7f91STakashi Iwai {
3635352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3636352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
3637352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
3638352f7f91STakashi Iwai 	bool have_multi_adcs;
3639352f7f91STakashi Iwai 
36401da177e4SLinus Torvalds 	codec->num_pcms = 1;
36411da177e4SLinus Torvalds 	codec->pcm_info = info;
36421da177e4SLinus Torvalds 
3643352f7f91STakashi Iwai 	if (spec->no_analog)
3644352f7f91STakashi Iwai 		goto skip_analog;
3645352f7f91STakashi Iwai 
3646f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
3647f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
3648f873e536STakashi Iwai 			     " Analog", codec->chip_name);
3649352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
3650352f7f91STakashi Iwai 
3651352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
3652352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
3653352f7f91STakashi Iwai 		if (!p)
3654352f7f91STakashi Iwai 			p = &pcm_analog_playback;
3655352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3656352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3657352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3658352f7f91STakashi Iwai 			spec->multiout.max_channels;
3659352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
3660352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
3661352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
3662352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
3663352f7f91STakashi Iwai 	}
3664352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
3665352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
3666352f7f91STakashi Iwai 		if (!p) {
3667352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
3668352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
3669352f7f91STakashi Iwai 			else
3670352f7f91STakashi Iwai 				p = &pcm_analog_capture;
3671352f7f91STakashi Iwai 		}
3672352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3673352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3674352f7f91STakashi Iwai 	}
3675352f7f91STakashi Iwai 
3676352f7f91STakashi Iwai  skip_analog:
3677352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
3678352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3679f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
3680352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
3681f873e536STakashi Iwai 				     " Digital", codec->chip_name);
3682352f7f91STakashi Iwai 		codec->num_pcms = 2;
3683352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
3684352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
3685352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
3686352f7f91STakashi Iwai 		if (spec->dig_out_type)
3687352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
3688352f7f91STakashi Iwai 		else
3689352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
3690352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
3691352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
3692352f7f91STakashi Iwai 			if (!p)
3693352f7f91STakashi Iwai 				p = &pcm_digital_playback;
3694352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3695352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3696352f7f91STakashi Iwai 		}
3697352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
3698352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
3699352f7f91STakashi Iwai 			if (!p)
3700352f7f91STakashi Iwai 				p = &pcm_digital_capture;
3701352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3702352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3703352f7f91STakashi Iwai 		}
3704352f7f91STakashi Iwai 	}
3705352f7f91STakashi Iwai 
3706352f7f91STakashi Iwai 	if (spec->no_analog)
3707352f7f91STakashi Iwai 		return 0;
3708352f7f91STakashi Iwai 
3709352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
3710352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
3711352f7f91STakashi Iwai 	 */
3712352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
3713352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
3714352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
3715352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
3716352f7f91STakashi Iwai 		codec->num_pcms = 3;
3717352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
3718352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
3719352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
3720352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
3721352f7f91STakashi Iwai 			if (!p)
3722352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
3723352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3724352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3725352f7f91STakashi Iwai 				spec->alt_dac_nid;
3726352f7f91STakashi Iwai 		} else {
3727352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3728352f7f91STakashi Iwai 				pcm_null_stream;
3729352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3730352f7f91STakashi Iwai 		}
3731352f7f91STakashi Iwai 		if (have_multi_adcs) {
3732352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
3733352f7f91STakashi Iwai 			if (!p)
3734352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
3735352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3736352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3737352f7f91STakashi Iwai 				spec->adc_nids[1];
3738352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3739352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
3740352f7f91STakashi Iwai 		} else {
3741352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3742352f7f91STakashi Iwai 				pcm_null_stream;
3743352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
3744352f7f91STakashi Iwai 		}
37451da177e4SLinus Torvalds 	}
37461da177e4SLinus Torvalds 
37471da177e4SLinus Torvalds 	return 0;
37481da177e4SLinus Torvalds }
3749352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
3750352f7f91STakashi Iwai 
3751352f7f91STakashi Iwai 
3752352f7f91STakashi Iwai /*
3753352f7f91STakashi Iwai  * Standard auto-parser initializations
3754352f7f91STakashi Iwai  */
3755352f7f91STakashi Iwai 
3756352f7f91STakashi Iwai /* configure the path from the given dac to the pin as the proper output */
3757352f7f91STakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, hda_nid_t pin,
3758196c1766STakashi Iwai 				  int pin_type, int path_idx)
3759352f7f91STakashi Iwai {
3760352f7f91STakashi Iwai 	struct nid_path *path;
3761352f7f91STakashi Iwai 
3762352f7f91STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, pin_type);
3763196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
3764352f7f91STakashi Iwai 	if (!path)
3765352f7f91STakashi Iwai 		return;
3766e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
3767e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
3768352f7f91STakashi Iwai }
3769352f7f91STakashi Iwai 
3770352f7f91STakashi Iwai /* initialize primary output paths */
3771352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
3772352f7f91STakashi Iwai {
3773352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3774196c1766STakashi Iwai 	hda_nid_t nid;
3775352f7f91STakashi Iwai 	int pin_type;
3776352f7f91STakashi Iwai 	int i;
3777352f7f91STakashi Iwai 
3778352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3779352f7f91STakashi Iwai 		pin_type = PIN_HP;
3780352f7f91STakashi Iwai 	else
3781352f7f91STakashi Iwai 		pin_type = PIN_OUT;
3782352f7f91STakashi Iwai 
378364049c81STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++) {
378464049c81STakashi Iwai 		nid = spec->autocfg.line_out_pins[i];
3785196c1766STakashi Iwai 		if (nid)
3786196c1766STakashi Iwai 			set_output_and_unmute(codec, nid, pin_type,
3787196c1766STakashi Iwai 					      spec->out_paths[i]);
3788352f7f91STakashi Iwai 	}
3789352f7f91STakashi Iwai }
3790352f7f91STakashi Iwai 
3791db23fd19STakashi Iwai 
3792db23fd19STakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs,
3793196c1766STakashi Iwai 			     hda_nid_t *pins, int *paths, int type)
3794352f7f91STakashi Iwai {
3795352f7f91STakashi Iwai 	int i;
3796196c1766STakashi Iwai 	hda_nid_t pin;
3797352f7f91STakashi Iwai 
3798db23fd19STakashi Iwai 	for (i = 0; i < num_outs; i++) {
3799db23fd19STakashi Iwai 		pin = pins[i];
3800352f7f91STakashi Iwai 		if (!pin)
3801352f7f91STakashi Iwai 			break;
3802196c1766STakashi Iwai 		set_output_and_unmute(codec, pin, type, paths[i]);
3803352f7f91STakashi Iwai 	}
3804352f7f91STakashi Iwai }
3805db23fd19STakashi Iwai 
3806db23fd19STakashi Iwai /* initialize hp and speaker paths */
3807db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
3808db23fd19STakashi Iwai {
3809db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3810db23fd19STakashi Iwai 
3811db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
3812db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs,
3813db23fd19STakashi Iwai 				 spec->autocfg.hp_pins,
3814196c1766STakashi Iwai 				 spec->hp_paths, PIN_HP);
3815db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
3816db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
3817db23fd19STakashi Iwai 				 spec->autocfg.speaker_pins,
3818196c1766STakashi Iwai 				 spec->speaker_paths, PIN_OUT);
3819352f7f91STakashi Iwai }
3820352f7f91STakashi Iwai 
3821352f7f91STakashi Iwai /* initialize multi-io paths */
3822352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
3823352f7f91STakashi Iwai {
3824352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3825352f7f91STakashi Iwai 	int i;
3826352f7f91STakashi Iwai 
3827352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
3828352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
3829352f7f91STakashi Iwai 		struct nid_path *path;
3830196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
3831352f7f91STakashi Iwai 		if (!path)
3832352f7f91STakashi Iwai 			continue;
3833352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
3834352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
3835352f7f91STakashi Iwai 				snd_hda_codec_update_cache(codec, pin, 0,
3836352f7f91STakashi Iwai 					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3837352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
3838352f7f91STakashi Iwai 	}
3839352f7f91STakashi Iwai }
3840352f7f91STakashi Iwai 
3841352f7f91STakashi Iwai /* set up the input pin config, depending on the given auto-pin type */
3842352f7f91STakashi Iwai static void set_input_pin(struct hda_codec *codec, hda_nid_t nid,
3843352f7f91STakashi Iwai 			  int auto_pin_type)
3844352f7f91STakashi Iwai {
3845352f7f91STakashi Iwai 	unsigned int val = PIN_IN;
3846352f7f91STakashi Iwai 	if (auto_pin_type == AUTO_PIN_MIC)
3847352f7f91STakashi Iwai 		val |= snd_hda_get_default_vref(codec, nid);
38487594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
3849352f7f91STakashi Iwai }
3850352f7f91STakashi Iwai 
3851352f7f91STakashi Iwai /* set up input pins and loopback paths */
3852352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
3853352f7f91STakashi Iwai {
3854352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3855352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3856352f7f91STakashi Iwai 	int i;
3857352f7f91STakashi Iwai 
3858352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3859352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3860352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
3861352f7f91STakashi Iwai 			set_input_pin(codec, nid, cfg->inputs[i].type);
3862352f7f91STakashi Iwai 
3863352f7f91STakashi Iwai 		/* init loopback inputs */
3864352f7f91STakashi Iwai 		if (spec->mixer_nid) {
3865352f7f91STakashi Iwai 			struct nid_path *path;
3866196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
3867352f7f91STakashi Iwai 			if (path)
3868352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
3869352f7f91STakashi Iwai 						      path->active, false);
3870352f7f91STakashi Iwai 		}
3871352f7f91STakashi Iwai 	}
3872352f7f91STakashi Iwai }
3873352f7f91STakashi Iwai 
3874352f7f91STakashi Iwai /* initialize ADC paths */
3875352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
3876352f7f91STakashi Iwai {
3877352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3878352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3879352f7f91STakashi Iwai 	struct nid_path *path;
3880352f7f91STakashi Iwai 	int i, c, nums;
3881352f7f91STakashi Iwai 
3882352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3883352f7f91STakashi Iwai 		nums = 1;
3884352f7f91STakashi Iwai 	else
3885352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3886352f7f91STakashi Iwai 
3887352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
3888352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3889352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
3890352f7f91STakashi Iwai 						    get_adc_nid(codec, c, i));
3891352f7f91STakashi Iwai 			if (path) {
3892352f7f91STakashi Iwai 				bool active = path->active;
3893352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
3894352f7f91STakashi Iwai 					active = true;
3895352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
3896352f7f91STakashi Iwai 			}
3897352f7f91STakashi Iwai 		}
3898352f7f91STakashi Iwai 	}
3899352f7f91STakashi Iwai 
3900352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3901352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
3902352f7f91STakashi Iwai 
3903352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3904352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
3905352f7f91STakashi Iwai }
3906352f7f91STakashi Iwai 
3907352f7f91STakashi Iwai /* set right pin controls for digital I/O */
3908352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
3909352f7f91STakashi Iwai {
3910352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3911352f7f91STakashi Iwai 	int i;
3912352f7f91STakashi Iwai 	hda_nid_t pin;
3913352f7f91STakashi Iwai 
3914352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
3915352f7f91STakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3916352f7f91STakashi Iwai 		if (!pin)
3917352f7f91STakashi Iwai 			continue;
3918196c1766STakashi Iwai 		set_output_and_unmute(codec, pin, PIN_OUT,
3919196c1766STakashi Iwai 				      spec->digout_paths[i]);
3920352f7f91STakashi Iwai 	}
3921352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
39222430d7b7STakashi Iwai 	if (pin) {
39232430d7b7STakashi Iwai 		struct nid_path *path;
39247594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, pin, PIN_IN);
39252430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
39262430d7b7STakashi Iwai 		if (path)
39272430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
39282430d7b7STakashi Iwai 	}
3929352f7f91STakashi Iwai }
3930352f7f91STakashi Iwai 
3931973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
3932973e4972STakashi Iwai  * invalid unsol tags by some reason
3933973e4972STakashi Iwai  */
3934973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
3935973e4972STakashi Iwai {
3936973e4972STakashi Iwai 	int i;
3937973e4972STakashi Iwai 
3938973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
3939973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
3940973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
3941973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
3942973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
3943973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
3944973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
3945973e4972STakashi Iwai 	}
3946973e4972STakashi Iwai }
3947973e4972STakashi Iwai 
3948352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
3949352f7f91STakashi Iwai {
3950352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3951352f7f91STakashi Iwai 
3952352f7f91STakashi Iwai 	if (spec->init_hook)
3953352f7f91STakashi Iwai 		spec->init_hook(codec);
3954352f7f91STakashi Iwai 
3955352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
3956352f7f91STakashi Iwai 
39573bbcd274STakashi Iwai 	codec->cached_write = 1;
39583bbcd274STakashi Iwai 
3959352f7f91STakashi Iwai 	init_multi_out(codec);
3960352f7f91STakashi Iwai 	init_extra_out(codec);
3961352f7f91STakashi Iwai 	init_multi_io(codec);
3962352f7f91STakashi Iwai 	init_analog_input(codec);
3963352f7f91STakashi Iwai 	init_input_src(codec);
3964352f7f91STakashi Iwai 	init_digital(codec);
3965352f7f91STakashi Iwai 
3966973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
3967973e4972STakashi Iwai 
3968352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
39695d550e15STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
39705d550e15STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
39715d550e15STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
3972352f7f91STakashi Iwai 
39733bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
39743bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
39753bbcd274STakashi Iwai 
3976352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
3977352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
3978352f7f91STakashi Iwai 
3979352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
3980352f7f91STakashi Iwai 	return 0;
3981352f7f91STakashi Iwai }
3982352f7f91STakashi Iwai EXPORT_SYMBOL(snd_hda_gen_init);
3983352f7f91STakashi Iwai 
3984352f7f91STakashi Iwai 
3985352f7f91STakashi Iwai /*
3986352f7f91STakashi Iwai  * the generic codec support
3987352f7f91STakashi Iwai  */
39881da177e4SLinus Torvalds 
398983012a7cSTakashi Iwai #ifdef CONFIG_PM
3990cb53c626STakashi Iwai static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3991cb53c626STakashi Iwai {
3992352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3993cb53c626STakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3994cb53c626STakashi Iwai }
3995cb53c626STakashi Iwai #endif
3996cb53c626STakashi Iwai 
3997352f7f91STakashi Iwai static void generic_free(struct hda_codec *codec)
3998352f7f91STakashi Iwai {
3999352f7f91STakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
4000352f7f91STakashi Iwai 	kfree(codec->spec);
4001352f7f91STakashi Iwai 	codec->spec = NULL;
4002352f7f91STakashi Iwai }
40031da177e4SLinus Torvalds 
4004352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
4005352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
4006352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
4007352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
4008352f7f91STakashi Iwai 	.free = generic_free,
4009352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
401083012a7cSTakashi Iwai #ifdef CONFIG_PM
4011cb53c626STakashi Iwai 	.check_power_status = generic_check_power_status,
4012cb53c626STakashi Iwai #endif
40131da177e4SLinus Torvalds };
40141da177e4SLinus Torvalds 
40151da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
40161da177e4SLinus Torvalds {
4017352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
40181da177e4SLinus Torvalds 	int err;
40191da177e4SLinus Torvalds 
4020e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4021352f7f91STakashi Iwai 	if (!spec)
40221da177e4SLinus Torvalds 		return -ENOMEM;
4023352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
40241da177e4SLinus Torvalds 	codec->spec = spec;
40251da177e4SLinus Torvalds 
40269eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
40279eb413e5STakashi Iwai 	if (err < 0)
40289eb413e5STakashi Iwai 		return err;
40299eb413e5STakashi Iwai 
40309eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
4031352f7f91STakashi Iwai 	if (err < 0)
40321da177e4SLinus Torvalds 		goto error;
40331da177e4SLinus Torvalds 
40341da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
40351da177e4SLinus Torvalds 	return 0;
40361da177e4SLinus Torvalds 
40371da177e4SLinus Torvalds error:
4038352f7f91STakashi Iwai 	generic_free(codec);
40391da177e4SLinus Torvalds 	return err;
40401da177e4SLinus Torvalds }
40411289e9e8STakashi Iwai EXPORT_SYMBOL(snd_hda_parse_generic_codec);
4042