xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision fce52a3b)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Generic widget tree parser
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  This driver is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
101da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
111da177e4SLinus Torvalds  *  (at your option) any later version.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *  This driver is distributed in the hope that it will be useful,
141da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
151da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4SLinus Torvalds  *  GNU General Public License for more details.
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  *  You should have received a copy of the GNU General Public License
191da177e4SLinus Torvalds  *  along with this program; if not, write to the Free Software
201da177e4SLinus Torvalds  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
211da177e4SLinus Torvalds  */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/slab.h>
25d81a6d71SPaul Gortmaker #include <linux/export.h>
26352f7f91STakashi Iwai #include <linux/sort.h>
27f873e536STakashi Iwai #include <linux/ctype.h>
28f873e536STakashi Iwai #include <linux/string.h>
291da177e4SLinus Torvalds #include <sound/core.h>
30352f7f91STakashi Iwai #include <sound/jack.h>
311da177e4SLinus Torvalds #include "hda_codec.h"
321da177e4SLinus Torvalds #include "hda_local.h"
33352f7f91STakashi Iwai #include "hda_auto_parser.h"
34352f7f91STakashi Iwai #include "hda_jack.h"
35352f7f91STakashi Iwai #include "hda_generic.h"
361da177e4SLinus Torvalds 
371da177e4SLinus Torvalds 
38352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
39352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
401da177e4SLinus Torvalds {
41352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
42352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
4338cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
44352f7f91STakashi Iwai 	return 0;
45352f7f91STakashi Iwai }
46352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
471da177e4SLinus Torvalds 
4812c93df6STakashi Iwai struct snd_kcontrol_new *
4912c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
50352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
51352f7f91STakashi Iwai {
52352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
53352f7f91STakashi Iwai 	if (!knew)
54352f7f91STakashi Iwai 		return NULL;
55352f7f91STakashi Iwai 	*knew = *temp;
56352f7f91STakashi Iwai 	if (name)
57352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
58352f7f91STakashi Iwai 	else if (knew->name)
59352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
60352f7f91STakashi Iwai 	if (!knew->name)
61352f7f91STakashi Iwai 		return NULL;
62352f7f91STakashi Iwai 	return knew;
63352f7f91STakashi Iwai }
6412c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
65352f7f91STakashi Iwai 
66352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
67352f7f91STakashi Iwai {
68352f7f91STakashi Iwai 	if (spec->kctls.list) {
69352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
70352f7f91STakashi Iwai 		int i;
71352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
72352f7f91STakashi Iwai 			kfree(kctl[i].name);
73352f7f91STakashi Iwai 	}
74352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
75352f7f91STakashi Iwai }
76352f7f91STakashi Iwai 
77352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
78352f7f91STakashi Iwai {
791da177e4SLinus Torvalds 	if (!spec)
801da177e4SLinus Torvalds 		return;
81352f7f91STakashi Iwai 	free_kctls(spec);
82352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
831da177e4SLinus Torvalds }
84352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
851da177e4SLinus Torvalds 
861da177e4SLinus Torvalds /*
87352f7f91STakashi Iwai  * parsing paths
881da177e4SLinus Torvalds  */
891da177e4SLinus Torvalds 
90f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
91f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
92f5172a7eSTakashi Iwai 				     int with_aa_mix)
931da177e4SLinus Torvalds {
94352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
95352f7f91STakashi Iwai 	int i;
961da177e4SLinus Torvalds 
97352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
98352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
99352f7f91STakashi Iwai 		if (path->depth <= 0)
100352f7f91STakashi Iwai 			continue;
101352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
102f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
103f5172a7eSTakashi Iwai 			if (with_aa_mix == HDA_PARSE_ALL ||
104f5172a7eSTakashi Iwai 			    path->with_aa_mix == with_aa_mix)
105352f7f91STakashi Iwai 				return path;
1061da177e4SLinus Torvalds 		}
107f5172a7eSTakashi Iwai 	}
1081da177e4SLinus Torvalds 	return NULL;
1091da177e4SLinus Torvalds }
110f5172a7eSTakashi Iwai 
111f5172a7eSTakashi Iwai /* get the path between the given NIDs;
112f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
113f5172a7eSTakashi Iwai  */
114f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
115f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
116f5172a7eSTakashi Iwai {
117f5172a7eSTakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, HDA_PARSE_ALL);
118f5172a7eSTakashi Iwai }
119352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
1201da177e4SLinus Torvalds 
121196c1766STakashi Iwai /* get the index number corresponding to the path instance;
122196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
123196c1766STakashi Iwai  */
124196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
125196c1766STakashi Iwai {
126196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
127196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
128196c1766STakashi Iwai 	ssize_t idx;
129196c1766STakashi Iwai 
130196c1766STakashi Iwai 	if (!spec->paths.used)
131196c1766STakashi Iwai 		return 0;
132196c1766STakashi Iwai 	idx = path - array;
133196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
134196c1766STakashi Iwai 		return 0;
135196c1766STakashi Iwai 	return idx + 1;
136196c1766STakashi Iwai }
137196c1766STakashi Iwai 
138196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
139196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
140196c1766STakashi Iwai {
141196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
142196c1766STakashi Iwai 
143196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
144196c1766STakashi Iwai 		return NULL;
145196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
146196c1766STakashi Iwai }
147196c1766STakashi Iwai 
148352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
149352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
1501da177e4SLinus Torvalds {
151352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
152352f7f91STakashi Iwai 	int i;
153352f7f91STakashi Iwai 
154352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
155352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
156352f7f91STakashi Iwai 		if (path->path[0] == nid)
157352f7f91STakashi Iwai 			return true;
158352f7f91STakashi Iwai 	}
159352f7f91STakashi Iwai 	return false;
1601da177e4SLinus Torvalds }
1611da177e4SLinus Torvalds 
162352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
163352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
164352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
1651da177e4SLinus Torvalds {
166352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
167352f7f91STakashi Iwai 		return false;
168352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
1691da177e4SLinus Torvalds }
1701da177e4SLinus Torvalds 
171352f7f91STakashi Iwai /* nid, dir and idx */
172352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
173352f7f91STakashi Iwai 
174352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
175352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
1761da177e4SLinus Torvalds {
177352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
178352f7f91STakashi Iwai 	int i;
179352f7f91STakashi Iwai 
180352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
181352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
182352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
183352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
184352f7f91STakashi Iwai 			return true;
185352f7f91STakashi Iwai 	}
186352f7f91STakashi Iwai 	return false;
1871da177e4SLinus Torvalds }
1881da177e4SLinus Torvalds 
189352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
190352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
191cb53c626STakashi Iwai 			      int dir, int idx)
192cb53c626STakashi Iwai {
193352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
194352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
195352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
196cb53c626STakashi Iwai }
197352f7f91STakashi Iwai 
1980c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
1990c8c0f56STakashi Iwai {
2000c8c0f56STakashi Iwai 	char buf[40];
2010c8c0f56STakashi Iwai 	int i;
2020c8c0f56STakashi Iwai 
2030c8c0f56STakashi Iwai 
2040c8c0f56STakashi Iwai 	buf[0] = 0;
2050c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
2060c8c0f56STakashi Iwai 		char tmp[4];
2070c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
2080c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
2090c8c0f56STakashi Iwai 	}
2100c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
2110c8c0f56STakashi Iwai }
2120c8c0f56STakashi Iwai 
213352f7f91STakashi Iwai /* called recursively */
214352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
215352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
216352f7f91STakashi Iwai 			     int with_aa_mix, struct nid_path *path, int depth)
217352f7f91STakashi Iwai {
218352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
219ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
220352f7f91STakashi Iwai 	int i, nums;
221352f7f91STakashi Iwai 
222352f7f91STakashi Iwai 	if (to_nid == spec->mixer_nid) {
2234ac0eefaSTakashi Iwai 		if (with_aa_mix == HDA_PARSE_NO_AAMIX)
224352f7f91STakashi Iwai 			return false;
2254ac0eefaSTakashi Iwai 		with_aa_mix = HDA_PARSE_ALL; /* mark aa-mix is included */
226352f7f91STakashi Iwai 	}
227352f7f91STakashi Iwai 
228ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
229352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
230352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
231352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
232352f7f91STakashi Iwai 			 * try to find an empty DAC
233352f7f91STakashi Iwai 			 */
234352f7f91STakashi Iwai 			if (from_nid ||
235352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
236352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
237352f7f91STakashi Iwai 				continue;
238352f7f91STakashi Iwai 		}
239352f7f91STakashi Iwai 		/* aa-mix is requested but not included? */
2404ac0eefaSTakashi Iwai 		if (!(spec->mixer_nid && with_aa_mix == HDA_PARSE_ONLY_AAMIX))
241352f7f91STakashi Iwai 			goto found;
242352f7f91STakashi Iwai 	}
243352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
244352f7f91STakashi Iwai 		return false;
245352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
246352f7f91STakashi Iwai 		unsigned int type;
247352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
248352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
249352f7f91STakashi Iwai 		    type == AC_WID_PIN)
250352f7f91STakashi Iwai 			continue;
251352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
252352f7f91STakashi Iwai 				     with_aa_mix, path, depth + 1))
253352f7f91STakashi Iwai 			goto found;
254352f7f91STakashi Iwai 	}
255352f7f91STakashi Iwai 	return false;
256352f7f91STakashi Iwai 
257352f7f91STakashi Iwai  found:
258352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
259f5172a7eSTakashi Iwai 	if (conn[i] == spec->mixer_nid)
260f5172a7eSTakashi Iwai 		path->with_aa_mix = true;
261352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
262352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
263352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
264352f7f91STakashi Iwai 	path->depth++;
265352f7f91STakashi Iwai 	return true;
266352f7f91STakashi Iwai }
267352f7f91STakashi Iwai 
268352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
269352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
2704ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_NO_AAMIX, paths with spec->mixer_nid are
2714ac0eefaSTakashi Iwai  * excluded, only the paths that don't go through the mixer will be chosen.
2724ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_ONLY_AAMIX, only the paths going through
2734ac0eefaSTakashi Iwai  * spec->mixer_nid will be chosen.
2744ac0eefaSTakashi Iwai  * when @with_aa_mix is HDA_PARSE_ALL, no special handling about mixer widget.
275352f7f91STakashi Iwai  */
276352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
277352f7f91STakashi Iwai 			    hda_nid_t to_nid, int with_aa_mix,
278352f7f91STakashi Iwai 			    struct nid_path *path)
279352f7f91STakashi Iwai {
280352f7f91STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) {
281352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
282352f7f91STakashi Iwai 		path->depth++;
283352f7f91STakashi Iwai 		return true;
284352f7f91STakashi Iwai 	}
285352f7f91STakashi Iwai 	return false;
286352f7f91STakashi Iwai }
287352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
288352f7f91STakashi Iwai 
289352f7f91STakashi Iwai /*
290352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
291352f7f91STakashi Iwai  * if no valid path is found, return NULL
292352f7f91STakashi Iwai  */
293352f7f91STakashi Iwai struct nid_path *
294352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
295352f7f91STakashi Iwai 		     hda_nid_t to_nid, int with_aa_mix)
296352f7f91STakashi Iwai {
297352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
298352f7f91STakashi Iwai 	struct nid_path *path;
299352f7f91STakashi Iwai 
300352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
301352f7f91STakashi Iwai 		return NULL;
302352f7f91STakashi Iwai 
303f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
304f5172a7eSTakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, with_aa_mix);
305f5172a7eSTakashi Iwai 	if (path)
306f5172a7eSTakashi Iwai 		return path;
307f5172a7eSTakashi Iwai 
308352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
309352f7f91STakashi Iwai 	if (!path)
310352f7f91STakashi Iwai 		return NULL;
311352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
312352f7f91STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path))
313352f7f91STakashi Iwai 		return path;
314352f7f91STakashi Iwai 	/* push back */
315352f7f91STakashi Iwai 	spec->paths.used--;
316352f7f91STakashi Iwai 	return NULL;
317352f7f91STakashi Iwai }
318352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
319352f7f91STakashi Iwai 
320352f7f91STakashi Iwai /* look for an empty DAC slot */
321352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
322352f7f91STakashi Iwai 			      bool is_digital)
323352f7f91STakashi Iwai {
324352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
325352f7f91STakashi Iwai 	bool cap_digital;
326352f7f91STakashi Iwai 	int i;
327352f7f91STakashi Iwai 
328352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
329352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
330352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
331352f7f91STakashi Iwai 			continue;
332352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
333352f7f91STakashi Iwai 		if (is_digital != cap_digital)
334352f7f91STakashi Iwai 			continue;
335352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
336352f7f91STakashi Iwai 			return nid;
337352f7f91STakashi Iwai 	}
338352f7f91STakashi Iwai 	return 0;
339352f7f91STakashi Iwai }
340352f7f91STakashi Iwai 
341352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
342352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
343352f7f91STakashi Iwai {
344352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
345352f7f91STakashi Iwai 	val |= chs << 16;
346352f7f91STakashi Iwai 	return val;
347352f7f91STakashi Iwai }
348352f7f91STakashi Iwai 
349352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
350352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
351352f7f91STakashi Iwai 			   int dir, unsigned int bits)
352352f7f91STakashi Iwai {
353352f7f91STakashi Iwai 	if (!nid)
354352f7f91STakashi Iwai 		return false;
355352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
356352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
357352f7f91STakashi Iwai 			return true;
358352f7f91STakashi Iwai 	return false;
359352f7f91STakashi Iwai }
360352f7f91STakashi Iwai 
361352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
362352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
363352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
364352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
365352f7f91STakashi Iwai 
366352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
367352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
368352f7f91STakashi Iwai 				       struct nid_path *path)
369352f7f91STakashi Iwai {
370352f7f91STakashi Iwai 	int i;
371352f7f91STakashi Iwai 
372352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
373352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
374352f7f91STakashi Iwai 			return path->path[i];
375352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
376352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
377352f7f91STakashi Iwai 			return path->path[i];
378352f7f91STakashi Iwai 	}
379352f7f91STakashi Iwai 	return 0;
380352f7f91STakashi Iwai }
381352f7f91STakashi Iwai 
382352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
383352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
384352f7f91STakashi Iwai 				      struct nid_path *path)
385352f7f91STakashi Iwai {
386352f7f91STakashi Iwai 	int i;
387352f7f91STakashi Iwai 
388352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
389352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
390352f7f91STakashi Iwai 			return path->path[i];
391352f7f91STakashi Iwai 	}
392352f7f91STakashi Iwai 	return 0;
393352f7f91STakashi Iwai }
394352f7f91STakashi Iwai 
395352f7f91STakashi Iwai /*
396352f7f91STakashi Iwai  * path activation / deactivation
397352f7f91STakashi Iwai  */
398352f7f91STakashi Iwai 
399352f7f91STakashi Iwai /* can have the amp-in capability? */
400352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
401352f7f91STakashi Iwai {
402352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
403352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
404352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
405352f7f91STakashi Iwai 
406352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
407352f7f91STakashi Iwai 		return false;
408352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
409352f7f91STakashi Iwai 		return false;
410352f7f91STakashi Iwai 	return true;
411352f7f91STakashi Iwai }
412352f7f91STakashi Iwai 
413352f7f91STakashi Iwai /* can have the amp-out capability? */
414352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
415352f7f91STakashi Iwai {
416352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
417352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
418352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
419352f7f91STakashi Iwai 
420352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
421352f7f91STakashi Iwai 		return false;
422352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
423352f7f91STakashi Iwai 		return false;
424352f7f91STakashi Iwai 	return true;
425352f7f91STakashi Iwai }
426352f7f91STakashi Iwai 
427352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
428352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
429352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
430352f7f91STakashi Iwai {
431352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
432352f7f91STakashi Iwai 	int i, n;
433352f7f91STakashi Iwai 
434352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
435352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
436352f7f91STakashi Iwai 		if (!path->active)
437352f7f91STakashi Iwai 			continue;
438352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
439352f7f91STakashi Iwai 			if (path->path[i] == nid) {
440352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
441352f7f91STakashi Iwai 					return true;
442352f7f91STakashi Iwai 				break;
443352f7f91STakashi Iwai 			}
444352f7f91STakashi Iwai 		}
445352f7f91STakashi Iwai 	}
446352f7f91STakashi Iwai 	return false;
447352f7f91STakashi Iwai }
448352f7f91STakashi Iwai 
449352f7f91STakashi Iwai /* get the default amp value for the target state */
450352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
451352f7f91STakashi Iwai 				   int dir, bool enable)
452352f7f91STakashi Iwai {
453352f7f91STakashi Iwai 	unsigned int caps;
454352f7f91STakashi Iwai 	unsigned int val = 0;
455352f7f91STakashi Iwai 
456352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
457352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
458352f7f91STakashi Iwai 		/* set to 0dB */
459352f7f91STakashi Iwai 		if (enable)
460352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
461352f7f91STakashi Iwai 	}
462352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
463352f7f91STakashi Iwai 		if (!enable)
464352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
465352f7f91STakashi Iwai 	}
466352f7f91STakashi Iwai 	return val;
467352f7f91STakashi Iwai }
468352f7f91STakashi Iwai 
469352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
470352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
471352f7f91STakashi Iwai {
472352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
473352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
474352f7f91STakashi Iwai }
475352f7f91STakashi Iwai 
476352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
477352f7f91STakashi Iwai 			 int idx, bool enable)
478352f7f91STakashi Iwai {
479352f7f91STakashi Iwai 	int val;
480352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
481985803caSTakashi Iwai 	    (!enable && is_active_nid(codec, nid, dir, idx)))
482352f7f91STakashi Iwai 		return;
483352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
484352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
485352f7f91STakashi Iwai }
486352f7f91STakashi Iwai 
487352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
488352f7f91STakashi Iwai 			     int i, bool enable)
489352f7f91STakashi Iwai {
490352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
491352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
492352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
493352f7f91STakashi Iwai }
494352f7f91STakashi Iwai 
495352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
496352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
497352f7f91STakashi Iwai {
498352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
499ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
500352f7f91STakashi Iwai 	int n, nums, idx;
501352f7f91STakashi Iwai 	int type;
502352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
503352f7f91STakashi Iwai 
504ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
505352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
506352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
507352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
508352f7f91STakashi Iwai 		nums = 1;
509352f7f91STakashi Iwai 		idx = 0;
510352f7f91STakashi Iwai 	} else
511352f7f91STakashi Iwai 		idx = path->idx[i];
512352f7f91STakashi Iwai 
513352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
514352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
515352f7f91STakashi Iwai 
516352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
517352f7f91STakashi Iwai 		return;
518352f7f91STakashi Iwai 
519352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
520352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
521352f7f91STakashi Iwai 	 */
522352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
523352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
524352f7f91STakashi Iwai 			continue;
525352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
526352f7f91STakashi Iwai 	}
527352f7f91STakashi Iwai }
528352f7f91STakashi Iwai 
529352f7f91STakashi Iwai /* activate or deactivate the given path
530352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
531352f7f91STakashi Iwai  */
532352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
533352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
534352f7f91STakashi Iwai {
535352f7f91STakashi Iwai 	int i;
536352f7f91STakashi Iwai 
537352f7f91STakashi Iwai 	if (!enable)
538352f7f91STakashi Iwai 		path->active = false;
539352f7f91STakashi Iwai 
540352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
541352f7f91STakashi Iwai 		if (enable && path->multi[i])
542352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
543352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
544352f7f91STakashi Iwai 					    path->idx[i]);
545352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
546352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
547352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
548352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
549352f7f91STakashi Iwai 	}
550352f7f91STakashi Iwai 
551352f7f91STakashi Iwai 	if (enable)
552352f7f91STakashi Iwai 		path->active = true;
553352f7f91STakashi Iwai }
554352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
555352f7f91STakashi Iwai 
556d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
557d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
558d5a9f1bbSTakashi Iwai {
559d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
560d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
561d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
562d5a9f1bbSTakashi Iwai 		return;
563ecac3ed1STakashi Iwai 	if (codec->inv_eapd)
564ecac3ed1STakashi Iwai 		enable = !enable;
565d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
566d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
567d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
568d5a9f1bbSTakashi Iwai }
569d5a9f1bbSTakashi Iwai 
570352f7f91STakashi Iwai 
571352f7f91STakashi Iwai /*
572352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
573352f7f91STakashi Iwai  */
574352f7f91STakashi Iwai 
575352f7f91STakashi Iwai enum {
576352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
577352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
578352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
579352f7f91STakashi Iwai 	HDA_CTL_BIND_VOL,
580352f7f91STakashi Iwai 	HDA_CTL_BIND_SW,
581352f7f91STakashi Iwai };
582352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
583352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
584352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
585352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
586352f7f91STakashi Iwai 	HDA_BIND_VOL(NULL, 0),
587352f7f91STakashi Iwai 	HDA_BIND_SW(NULL, 0),
588352f7f91STakashi Iwai };
589352f7f91STakashi Iwai 
590352f7f91STakashi Iwai /* add dynamic controls from template */
591352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
592352f7f91STakashi Iwai 		       int cidx, unsigned long val)
593352f7f91STakashi Iwai {
594352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
595352f7f91STakashi Iwai 
59612c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
597352f7f91STakashi Iwai 	if (!knew)
598352f7f91STakashi Iwai 		return -ENOMEM;
599352f7f91STakashi Iwai 	knew->index = cidx;
600352f7f91STakashi Iwai 	if (get_amp_nid_(val))
601352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
602352f7f91STakashi Iwai 	knew->private_value = val;
603352f7f91STakashi Iwai 	return 0;
604352f7f91STakashi Iwai }
605352f7f91STakashi Iwai 
606352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
607352f7f91STakashi Iwai 				const char *pfx, const char *dir,
608352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
609352f7f91STakashi Iwai {
610352f7f91STakashi Iwai 	char name[32];
611352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
612352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
613352f7f91STakashi Iwai }
614352f7f91STakashi Iwai 
615352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
616352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
617352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
618352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
619352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
620352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
621352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
622352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
623352f7f91STakashi Iwai 
624352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
625352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
626352f7f91STakashi Iwai {
627352f7f91STakashi Iwai 	unsigned int val;
628352f7f91STakashi Iwai 	if (!path)
629352f7f91STakashi Iwai 		return 0;
630352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
631352f7f91STakashi Iwai 	if (!val)
632352f7f91STakashi Iwai 		return 0;
633352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
634352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
635352f7f91STakashi Iwai }
636352f7f91STakashi Iwai 
637352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
638352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
639352f7f91STakashi Iwai 			       int type)
640352f7f91STakashi Iwai {
641352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
642352f7f91STakashi Iwai 	if (path) {
643352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
644352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
645352f7f91STakashi Iwai 			chs = 3; /* stereo */
646352f7f91STakashi Iwai 	}
647352f7f91STakashi Iwai 	return chs;
648352f7f91STakashi Iwai }
649352f7f91STakashi Iwai 
650352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
651352f7f91STakashi Iwai 			  struct nid_path *path)
652352f7f91STakashi Iwai {
653352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
654352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
655352f7f91STakashi Iwai }
656352f7f91STakashi Iwai 
657352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
658352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
659352f7f91STakashi Iwai  */
660352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
661352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
662352f7f91STakashi Iwai {
663352f7f91STakashi Iwai 	unsigned int val;
664352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
665352f7f91STakashi Iwai 
666352f7f91STakashi Iwai 	if (!path)
667352f7f91STakashi Iwai 		return 0;
668352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
669352f7f91STakashi Iwai 	if (!val)
670352f7f91STakashi Iwai 		return 0;
671352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
672352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
673352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
674352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
675352f7f91STakashi Iwai 		if (nums > 1) {
676352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
677352f7f91STakashi Iwai 			val |= nums << 19;
678352f7f91STakashi Iwai 		}
679352f7f91STakashi Iwai 	}
680352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
681352f7f91STakashi Iwai }
682352f7f91STakashi Iwai 
683352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
684352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
685352f7f91STakashi Iwai {
686352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
687352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
688352f7f91STakashi Iwai }
689352f7f91STakashi Iwai 
690352f7f91STakashi Iwai static const char * const channel_name[4] = {
691352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
692352f7f91STakashi Iwai };
693352f7f91STakashi Iwai 
694352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
695352f7f91STakashi Iwai static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch,
696352f7f91STakashi Iwai 				    bool can_be_master, int *index)
697352f7f91STakashi Iwai {
698352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
699352f7f91STakashi Iwai 
700352f7f91STakashi Iwai 	*index = 0;
701352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
702352f7f91STakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
703352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
704352f7f91STakashi Iwai 
705352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
706352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
707352f7f91STakashi Iwai 	 */
708352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
709352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
710352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
711352f7f91STakashi Iwai 
712352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
713352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
714352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
715352f7f91STakashi Iwai 			return "Speaker";
716352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
717352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
718352f7f91STakashi Iwai 		break;
719352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
720352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
721352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
722352f7f91STakashi Iwai 			break;
723352f7f91STakashi Iwai 		*index = ch;
724352f7f91STakashi Iwai 		return "Headphone";
725352f7f91STakashi Iwai 	default:
726352f7f91STakashi Iwai 		if (cfg->line_outs == 1 && !spec->multi_ios)
727352f7f91STakashi Iwai 			return "PCM";
728352f7f91STakashi Iwai 		break;
729352f7f91STakashi Iwai 	}
730352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
731352f7f91STakashi Iwai 		snd_BUG();
732352f7f91STakashi Iwai 		return "PCM";
733352f7f91STakashi Iwai 	}
734352f7f91STakashi Iwai 
735352f7f91STakashi Iwai 	return channel_name[ch];
736352f7f91STakashi Iwai }
737352f7f91STakashi Iwai 
738352f7f91STakashi Iwai /*
739352f7f91STakashi Iwai  * Parse output paths
740352f7f91STakashi Iwai  */
741352f7f91STakashi Iwai 
742352f7f91STakashi Iwai /* badness definition */
743352f7f91STakashi Iwai enum {
744352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
745352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
746352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
747352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
748352f7f91STakashi Iwai 	/* No possible multi-ios */
749352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
750352f7f91STakashi Iwai 	/* No individual DAC for extra output */
751352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
752352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
753352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
754352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
755352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
756352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
757352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
758352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
759352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
760352f7f91STakashi Iwai 	/* Volume widget is shared */
761352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
762352f7f91STakashi Iwai };
763352f7f91STakashi Iwai 
764352f7f91STakashi Iwai /* look for widgets in the path between the given NIDs appropriate for
765352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
766352f7f91STakashi Iwai  *
767352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
768352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
769352f7f91STakashi Iwai  * total badness for both volume and mute controls.
770352f7f91STakashi Iwai  */
771352f7f91STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, hda_nid_t pin,
772352f7f91STakashi Iwai 				hda_nid_t dac)
773352f7f91STakashi Iwai {
774352f7f91STakashi Iwai 	struct nid_path *path = snd_hda_get_nid_path(codec, dac, pin);
775352f7f91STakashi Iwai 	hda_nid_t nid;
776352f7f91STakashi Iwai 	unsigned int val;
777352f7f91STakashi Iwai 	int badness = 0;
778352f7f91STakashi Iwai 
779352f7f91STakashi Iwai 	if (!path)
780352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
781352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
782352f7f91STakashi Iwai 	if (nid) {
783352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
784352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
785352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
786352f7f91STakashi Iwai 		else
787352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
788352f7f91STakashi Iwai 	} else
789352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
790352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
791352f7f91STakashi Iwai 	if (nid) {
792352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
793352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
794352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
795352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
796352f7f91STakashi Iwai 		else
797352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
798352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
799352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
800352f7f91STakashi Iwai 		else
801352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
802352f7f91STakashi Iwai 	} else
803352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
804352f7f91STakashi Iwai 	return badness;
805352f7f91STakashi Iwai }
806352f7f91STakashi Iwai 
807352f7f91STakashi Iwai struct badness_table {
808352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
809352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
810352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
811352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
812352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
813352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
814352f7f91STakashi Iwai };
815352f7f91STakashi Iwai 
816352f7f91STakashi Iwai static struct badness_table main_out_badness = {
817352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
818352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
819352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
820352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
821352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
822352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
823352f7f91STakashi Iwai };
824352f7f91STakashi Iwai 
825352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
826352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
827352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
828352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
829352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
830352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
831352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
832352f7f91STakashi Iwai };
833352f7f91STakashi Iwai 
8347385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
8357385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
8367385df61STakashi Iwai {
8377385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
8387385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
8397385df61STakashi Iwai 
8407385df61STakashi Iwai 	if (cfg->line_outs > idx)
8417385df61STakashi Iwai 		return spec->private_dac_nids[idx];
8427385df61STakashi Iwai 	idx -= cfg->line_outs;
8437385df61STakashi Iwai 	if (spec->multi_ios > idx)
8447385df61STakashi Iwai 		return spec->multi_io[idx].dac;
8457385df61STakashi Iwai 	return 0;
8467385df61STakashi Iwai }
8477385df61STakashi Iwai 
8487385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
8497385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
8507385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
8517385df61STakashi Iwai {
8527385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
8537385df61STakashi Iwai }
8547385df61STakashi Iwai 
855352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
856352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
857352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
858196c1766STakashi Iwai 			   int *path_idx,
859352f7f91STakashi Iwai 			   const struct badness_table *bad)
860352f7f91STakashi Iwai {
861352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
862352f7f91STakashi Iwai 	int i, j;
863352f7f91STakashi Iwai 	int badness = 0;
864352f7f91STakashi Iwai 	hda_nid_t dac;
865352f7f91STakashi Iwai 
866352f7f91STakashi Iwai 	if (!num_outs)
867352f7f91STakashi Iwai 		return 0;
868352f7f91STakashi Iwai 
869352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
8700c8c0f56STakashi Iwai 		struct nid_path *path;
871352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
8721e0b5286STakashi Iwai 
8731e0b5286STakashi Iwai 		if (dacs[i]) {
8741e0b5286STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dacs[i]);
8751e0b5286STakashi Iwai 			continue;
8761e0b5286STakashi Iwai 		}
8771e0b5286STakashi Iwai 
878352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
879352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
880352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
881352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
882352f7f91STakashi Iwai 					dacs[0] = dacs[j];
883352f7f91STakashi Iwai 					dacs[j] = 0;
884196c1766STakashi Iwai 					path_idx[j] = 0;
885352f7f91STakashi Iwai 					break;
886352f7f91STakashi Iwai 				}
887352f7f91STakashi Iwai 			}
888352f7f91STakashi Iwai 		}
889352f7f91STakashi Iwai 		dac = dacs[i];
890352f7f91STakashi Iwai 		if (!dac) {
8917385df61STakashi Iwai 			if (num_outs > 2)
8927385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
8937385df61STakashi Iwai 			if (!dac)
8947385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
8957385df61STakashi Iwai 			if (!dac)
8967385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
897352f7f91STakashi Iwai 			if (dac) {
898352f7f91STakashi Iwai 				if (!i)
899352f7f91STakashi Iwai 					badness += bad->shared_primary;
900352f7f91STakashi Iwai 				else if (i == 1)
901352f7f91STakashi Iwai 					badness += bad->shared_surr;
902352f7f91STakashi Iwai 				else
903352f7f91STakashi Iwai 					badness += bad->shared_clfe;
904352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
905352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
906352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
907352f7f91STakashi Iwai 			} else if (!i)
908352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
909352f7f91STakashi Iwai 			else
910352f7f91STakashi Iwai 				badness += bad->no_dac;
911352f7f91STakashi Iwai 		}
9124ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_NO_AAMIX);
913117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
914b3a8c745STakashi Iwai 			/* try with aamix */
915b3a8c745STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, HDA_PARSE_ALL);
916b3a8c745STakashi Iwai 		}
9170c8c0f56STakashi Iwai 		if (!path)
918352f7f91STakashi Iwai 			dac = dacs[i] = 0;
919e1284af7STakashi Iwai 		else {
9200c8c0f56STakashi Iwai 			print_nid_path("output", path);
921e1284af7STakashi Iwai 			path->active = true;
922196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
923e1284af7STakashi Iwai 		}
924352f7f91STakashi Iwai 		if (dac)
925352f7f91STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dac);
926352f7f91STakashi Iwai 	}
927352f7f91STakashi Iwai 
928352f7f91STakashi Iwai 	return badness;
929352f7f91STakashi Iwai }
930352f7f91STakashi Iwai 
931352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
932352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
933352f7f91STakashi Iwai {
934352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
935352f7f91STakashi Iwai 	int i;
936352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
937352f7f91STakashi Iwai 
938352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
939352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
940352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
941352f7f91STakashi Iwai 			continue;
942352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
943352f7f91STakashi Iwai 			if (nid_found)
944352f7f91STakashi Iwai 				return 0;
945352f7f91STakashi Iwai 			nid_found = nid;
946352f7f91STakashi Iwai 		}
947352f7f91STakashi Iwai 	}
948352f7f91STakashi Iwai 	return nid_found;
949352f7f91STakashi Iwai }
950352f7f91STakashi Iwai 
951352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
952352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
953352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
954352f7f91STakashi Iwai {
955352f7f91STakashi Iwai 	unsigned int defcfg, caps;
956352f7f91STakashi Iwai 
957352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
958352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
959352f7f91STakashi Iwai 		return false;
960352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
961352f7f91STakashi Iwai 		return false;
962352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
963352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
964352f7f91STakashi Iwai 		return false;
965352f7f91STakashi Iwai 	return true;
966352f7f91STakashi Iwai }
967352f7f91STakashi Iwai 
968e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
969e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
970e22aab7dSTakashi Iwai {
971e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
972e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
973e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
974e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
975e22aab7dSTakashi Iwai 	int type, i;
976e22aab7dSTakashi Iwai 	int num_pins = 0;
977e22aab7dSTakashi Iwai 
978e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
979e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
980e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
981e22aab7dSTakashi Iwai 				continue;
982e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
983e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
984e22aab7dSTakashi Iwai 				num_pins++;
985e22aab7dSTakashi Iwai 		}
986e22aab7dSTakashi Iwai 	}
987e22aab7dSTakashi Iwai 	return num_pins;
988e22aab7dSTakashi Iwai }
989e22aab7dSTakashi Iwai 
990352f7f91STakashi Iwai /*
991352f7f91STakashi Iwai  * multi-io helper
992352f7f91STakashi Iwai  *
993352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
994352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
995352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
996352f7f91STakashi Iwai  * the badness value.
997352f7f91STakashi Iwai  */
998352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
999352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1000e22aab7dSTakashi Iwai 			  bool hardwired)
1001352f7f91STakashi Iwai {
1002352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1003352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1004e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1005352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1006352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1007352f7f91STakashi Iwai 	int badness = 0;
1008352f7f91STakashi Iwai 
1009352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1010352f7f91STakashi Iwai 	if (old_pins >= 2)
1011352f7f91STakashi Iwai 		goto end_fill;
1012352f7f91STakashi Iwai 
1013e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1014352f7f91STakashi Iwai 	if (num_pins < 2)
1015352f7f91STakashi Iwai 		goto end_fill;
1016352f7f91STakashi Iwai 
1017352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1018352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
10190c8c0f56STakashi Iwai 			struct nid_path *path;
1020352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1021352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1022352f7f91STakashi Iwai 
1023352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1024352f7f91STakashi Iwai 				continue;
1025352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1026352f7f91STakashi Iwai 				continue;
1027352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1028352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1029352f7f91STakashi Iwai 					break;
1030352f7f91STakashi Iwai 			}
1031352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1032352f7f91STakashi Iwai 				continue;
1033352f7f91STakashi Iwai 
1034352f7f91STakashi Iwai 			if (hardwired)
1035352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1036352f7f91STakashi Iwai 			else if (!dac)
1037352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1038352f7f91STakashi Iwai 			if (!dac) {
1039352f7f91STakashi Iwai 				badness++;
1040352f7f91STakashi Iwai 				continue;
1041352f7f91STakashi Iwai 			}
10424ac0eefaSTakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid, HDA_PARSE_NO_AAMIX);
10430c8c0f56STakashi Iwai 			if (!path) {
1044352f7f91STakashi Iwai 				badness++;
1045352f7f91STakashi Iwai 				continue;
1046352f7f91STakashi Iwai 			}
10470c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1048352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1049352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1050196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1051196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1052352f7f91STakashi Iwai 			spec->multi_ios++;
1053352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1054352f7f91STakashi Iwai 				break;
1055352f7f91STakashi Iwai 		}
1056352f7f91STakashi Iwai 	}
1057352f7f91STakashi Iwai  end_fill:
1058352f7f91STakashi Iwai 	if (badness)
1059352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1060352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1061352f7f91STakashi Iwai 		if (hardwired)
1062352f7f91STakashi Iwai 			return 1; /* nothing found */
1063352f7f91STakashi Iwai 		else
1064352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1065352f7f91STakashi Iwai 	}
1066352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1067352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1068352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1069352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1070352f7f91STakashi Iwai 		return badness;
1071352f7f91STakashi Iwai 	}
1072352f7f91STakashi Iwai 
1073352f7f91STakashi Iwai 	/* assign volume and mute controls */
1074352f7f91STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++)
1075352f7f91STakashi Iwai 		badness += assign_out_path_ctls(codec, spec->multi_io[i].pin,
1076352f7f91STakashi Iwai 						spec->multi_io[i].dac);
1077352f7f91STakashi Iwai 
1078352f7f91STakashi Iwai 	return badness;
1079352f7f91STakashi Iwai }
1080352f7f91STakashi Iwai 
1081352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1082352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1083196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1084352f7f91STakashi Iwai {
1085b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1086352f7f91STakashi Iwai 	int i;
1087352f7f91STakashi Iwai 	bool found = false;
1088352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
10890c8c0f56STakashi Iwai 		struct nid_path *path;
1090352f7f91STakashi Iwai 		hda_nid_t dac;
1091352f7f91STakashi Iwai 		if (dacs[i])
1092352f7f91STakashi Iwai 			continue;
1093352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1094352f7f91STakashi Iwai 		if (!dac)
1095352f7f91STakashi Iwai 			continue;
10964ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_NO_AAMIX);
1097117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
1098b3a8c745STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], HDA_PARSE_ALL);
10990c8c0f56STakashi Iwai 		if (path) {
1100352f7f91STakashi Iwai 			dacs[i] = dac;
1101352f7f91STakashi Iwai 			found = true;
11020c8c0f56STakashi Iwai 			print_nid_path("output", path);
1103e1284af7STakashi Iwai 			path->active = true;
1104196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1105352f7f91STakashi Iwai 		}
1106352f7f91STakashi Iwai 	}
1107352f7f91STakashi Iwai 	return found;
1108352f7f91STakashi Iwai }
1109352f7f91STakashi Iwai 
1110c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1111c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1112c30aa7b2STakashi Iwai {
1113c30aa7b2STakashi Iwai 	struct nid_path *path;
1114c30aa7b2STakashi Iwai 
1115c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1116c30aa7b2STakashi Iwai 	if (!path || !path->depth || path->with_aa_mix)
1117c30aa7b2STakashi Iwai 		return 0;
1118c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1119c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
1120c30aa7b2STakashi Iwai 				    HDA_PARSE_ONLY_AAMIX);
1121c30aa7b2STakashi Iwai 	if (!path)
1122c30aa7b2STakashi Iwai 		return 0;
1123c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1124c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1125c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1126c30aa7b2STakashi Iwai }
1127c30aa7b2STakashi Iwai 
1128352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1129352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1130352f7f91STakashi Iwai 			      bool fill_hardwired,
1131352f7f91STakashi Iwai 			      bool fill_mio_first)
1132352f7f91STakashi Iwai {
1133352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1134352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1135352f7f91STakashi Iwai 	int i, err, badness;
1136352f7f91STakashi Iwai 
1137352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1138352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1139352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1140352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1141352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1142352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1143352f7f91STakashi Iwai 	spec->multi_ios = 0;
1144352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1145352f7f91STakashi Iwai 	badness = 0;
1146352f7f91STakashi Iwai 
1147352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1148352f7f91STakashi Iwai 	if (fill_hardwired) {
1149352f7f91STakashi Iwai 		bool mapped;
1150352f7f91STakashi Iwai 		do {
1151352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1152352f7f91STakashi Iwai 					     cfg->line_out_pins,
1153196c1766STakashi Iwai 					     spec->private_dac_nids,
1154196c1766STakashi Iwai 					     spec->out_paths);
1155352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1156352f7f91STakashi Iwai 					      cfg->hp_pins,
1157196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1158196c1766STakashi Iwai 					      spec->hp_paths);
1159352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1160352f7f91STakashi Iwai 					      cfg->speaker_pins,
1161196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1162196c1766STakashi Iwai 					      spec->speaker_paths);
1163352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1164352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1165e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1166352f7f91STakashi Iwai 				if (!err)
1167352f7f91STakashi Iwai 					mapped = true;
1168352f7f91STakashi Iwai 			}
1169352f7f91STakashi Iwai 		} while (mapped);
1170352f7f91STakashi Iwai 	}
1171352f7f91STakashi Iwai 
1172352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1173196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1174352f7f91STakashi Iwai 				   &main_out_badness);
1175352f7f91STakashi Iwai 
1176352f7f91STakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1177352f7f91STakashi Iwai 	spec->multiout.num_dacs = 0;
1178352f7f91STakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1179352f7f91STakashi Iwai 		if (spec->private_dac_nids[i])
1180352f7f91STakashi Iwai 			spec->multiout.num_dacs++;
1181352f7f91STakashi Iwai 		else {
1182352f7f91STakashi Iwai 			memmove(spec->private_dac_nids + i,
1183352f7f91STakashi Iwai 				spec->private_dac_nids + i + 1,
1184352f7f91STakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1185352f7f91STakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1186352f7f91STakashi Iwai 		}
1187352f7f91STakashi Iwai 	}
1188352f7f91STakashi Iwai 
1189352f7f91STakashi Iwai 	if (fill_mio_first &&
1190352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1191352f7f91STakashi Iwai 		/* try to fill multi-io first */
1192e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1193352f7f91STakashi Iwai 		if (err < 0)
1194352f7f91STakashi Iwai 			return err;
1195352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1196352f7f91STakashi Iwai 	}
1197352f7f91STakashi Iwai 
1198352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1199352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1200352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1201196c1766STakashi Iwai 				      spec->hp_paths,
1202352f7f91STakashi Iwai 				      &extra_out_badness);
1203352f7f91STakashi Iwai 		if (err < 0)
1204352f7f91STakashi Iwai 			return err;
1205352f7f91STakashi Iwai 		badness += err;
1206352f7f91STakashi Iwai 	}
1207352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1208352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1209352f7f91STakashi Iwai 				      cfg->speaker_pins,
1210352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1211196c1766STakashi Iwai 				      spec->speaker_paths,
1212352f7f91STakashi Iwai 				      &extra_out_badness);
1213352f7f91STakashi Iwai 		if (err < 0)
1214352f7f91STakashi Iwai 			return err;
1215352f7f91STakashi Iwai 		badness += err;
1216352f7f91STakashi Iwai 	}
1217352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1218e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1219352f7f91STakashi Iwai 		if (err < 0)
1220352f7f91STakashi Iwai 			return err;
1221352f7f91STakashi Iwai 		badness += err;
1222352f7f91STakashi Iwai 	}
1223e22aab7dSTakashi Iwai 
1224c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1225c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1226c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1227c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1228c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1229c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1230c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1231c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1232c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1233c30aa7b2STakashi Iwai 	}
1234c30aa7b2STakashi Iwai 
1235e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1236e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1237e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1238352f7f91STakashi Iwai 
1239352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1240352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1241352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1242352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1243352f7f91STakashi Iwai 		spec->ext_channel_count = 2;
1244352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1245352f7f91STakashi Iwai 		spec->multi_ios = 0;
1246352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1247352f7f91STakashi Iwai 	}
1248352f7f91STakashi Iwai 
1249352f7f91STakashi Iwai 	return badness;
1250352f7f91STakashi Iwai }
1251352f7f91STakashi Iwai 
1252352f7f91STakashi Iwai #define DEBUG_BADNESS
1253352f7f91STakashi Iwai 
1254352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1255352f7f91STakashi Iwai #define debug_badness	snd_printdd
1256352f7f91STakashi Iwai #else
1257352f7f91STakashi Iwai #define debug_badness(...)
1258352f7f91STakashi Iwai #endif
1259352f7f91STakashi Iwai 
1260352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1261352f7f91STakashi Iwai {
1262352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1263352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1264708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1265352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1266352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1267352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1268352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1269352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1270352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1271352f7f91STakashi Iwai 			      spec->multi_ios,
1272352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1273352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1274352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1275352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1276708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1277352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1278352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1279352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1280352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1281352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1282352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1283352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1284352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1285352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1286352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1287352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1288352f7f91STakashi Iwai }
1289352f7f91STakashi Iwai 
1290352f7f91STakashi Iwai /* find all available DACs of the codec */
1291352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1292352f7f91STakashi Iwai {
1293352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1294352f7f91STakashi Iwai 	int i;
1295352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1296352f7f91STakashi Iwai 
1297352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1298352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1299352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1300352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1301352f7f91STakashi Iwai 			continue;
1302352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1303352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1304352f7f91STakashi Iwai 			break;
1305352f7f91STakashi Iwai 		}
1306352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1307352f7f91STakashi Iwai 	}
1308352f7f91STakashi Iwai }
1309352f7f91STakashi Iwai 
1310352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1311352f7f91STakashi Iwai {
1312352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1313352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1314352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1315352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1316352f7f91STakashi Iwai 	int badness;
1317352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1318352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1319352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1320352f7f91STakashi Iwai 
1321352f7f91STakashi Iwai 	fill_all_dac_nids(codec);
1322352f7f91STakashi Iwai 
1323352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1324352f7f91STakashi Iwai 	if (!best_cfg)
1325352f7f91STakashi Iwai 		return -ENOMEM;
1326352f7f91STakashi Iwai 	*best_cfg = *cfg;
1327352f7f91STakashi Iwai 
1328352f7f91STakashi Iwai 	for (;;) {
1329352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1330352f7f91STakashi Iwai 					     fill_mio_first);
1331352f7f91STakashi Iwai 		if (badness < 0) {
1332352f7f91STakashi Iwai 			kfree(best_cfg);
1333352f7f91STakashi Iwai 			return badness;
1334352f7f91STakashi Iwai 		}
1335352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1336352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1337352f7f91STakashi Iwai 			      badness);
1338352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1339352f7f91STakashi Iwai 		if (badness < best_badness) {
1340352f7f91STakashi Iwai 			best_badness = badness;
1341352f7f91STakashi Iwai 			*best_cfg = *cfg;
1342352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1343352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1344352f7f91STakashi Iwai 		}
1345352f7f91STakashi Iwai 		if (!badness)
1346352f7f91STakashi Iwai 			break;
1347352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1348352f7f91STakashi Iwai 		if (!fill_mio_first)
1349352f7f91STakashi Iwai 			continue;
1350352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1351352f7f91STakashi Iwai 		if (!fill_hardwired)
1352352f7f91STakashi Iwai 			continue;
1353352f7f91STakashi Iwai 		if (hp_spk_swapped)
1354352f7f91STakashi Iwai 			break;
1355352f7f91STakashi Iwai 		hp_spk_swapped = true;
1356352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1357352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1358352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1359352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1360352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1361352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1362352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1363352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1364352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1365352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1366352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1367352f7f91STakashi Iwai 			fill_hardwired = true;
1368352f7f91STakashi Iwai 			continue;
1369352f7f91STakashi Iwai 		}
1370352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1371352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1372352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1373352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1374352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1375352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1376352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1377352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1378352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1379352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1380352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1381352f7f91STakashi Iwai 			fill_hardwired = true;
1382352f7f91STakashi Iwai 			continue;
1383352f7f91STakashi Iwai 		}
1384352f7f91STakashi Iwai 		break;
1385352f7f91STakashi Iwai 	}
1386352f7f91STakashi Iwai 
1387352f7f91STakashi Iwai 	if (badness) {
13880c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1389352f7f91STakashi Iwai 		*cfg = *best_cfg;
1390352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1391352f7f91STakashi Iwai 	}
1392352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1393352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1394352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1395352f7f91STakashi Iwai 
1396352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1397352f7f91STakashi Iwai 		struct nid_path *path;
1398196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1399352f7f91STakashi Iwai 		if (path)
1400352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1401352f7f91STakashi Iwai 	}
1402352f7f91STakashi Iwai 
1403352f7f91STakashi Iwai 	kfree(best_cfg);
1404352f7f91STakashi Iwai 	return 0;
1405352f7f91STakashi Iwai }
1406352f7f91STakashi Iwai 
1407352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1408352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1409352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1410352f7f91STakashi Iwai {
1411352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1412352f7f91STakashi Iwai 	int i, err, noutputs;
1413352f7f91STakashi Iwai 
1414352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1415352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1416352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1417352f7f91STakashi Iwai 
1418352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1419352f7f91STakashi Iwai 		const char *name;
1420352f7f91STakashi Iwai 		int index;
1421196c1766STakashi Iwai 		hda_nid_t dac;
1422352f7f91STakashi Iwai 		struct nid_path *path;
1423352f7f91STakashi Iwai 
1424352f7f91STakashi Iwai 		dac = spec->multiout.dac_nids[i];
1425352f7f91STakashi Iwai 		if (!dac)
1426352f7f91STakashi Iwai 			continue;
1427352f7f91STakashi Iwai 		if (i >= cfg->line_outs) {
1428352f7f91STakashi Iwai 			index = 0;
1429352f7f91STakashi Iwai 			name = channel_name[i];
1430352f7f91STakashi Iwai 		} else {
1431352f7f91STakashi Iwai 			name = get_line_out_pfx(spec, i, true, &index);
1432352f7f91STakashi Iwai 		}
1433352f7f91STakashi Iwai 
1434196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1435352f7f91STakashi Iwai 		if (!path)
1436352f7f91STakashi Iwai 			continue;
1437352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1438352f7f91STakashi Iwai 			/* Center/LFE */
1439352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1440352f7f91STakashi Iwai 			if (err < 0)
1441352f7f91STakashi Iwai 				return err;
1442352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1443352f7f91STakashi Iwai 			if (err < 0)
1444352f7f91STakashi Iwai 				return err;
1445352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1446352f7f91STakashi Iwai 			if (err < 0)
1447352f7f91STakashi Iwai 				return err;
1448352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1449352f7f91STakashi Iwai 			if (err < 0)
1450352f7f91STakashi Iwai 				return err;
1451352f7f91STakashi Iwai 		} else {
1452352f7f91STakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1453352f7f91STakashi Iwai 			if (err < 0)
1454352f7f91STakashi Iwai 				return err;
1455352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1456352f7f91STakashi Iwai 			if (err < 0)
1457352f7f91STakashi Iwai 				return err;
1458352f7f91STakashi Iwai 		}
1459352f7f91STakashi Iwai 	}
1460352f7f91STakashi Iwai 	return 0;
1461352f7f91STakashi Iwai }
1462352f7f91STakashi Iwai 
1463c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1464196c1766STakashi Iwai 			    const char *pfx, int cidx)
1465352f7f91STakashi Iwai {
1466352f7f91STakashi Iwai 	struct nid_path *path;
1467352f7f91STakashi Iwai 	int err;
1468352f7f91STakashi Iwai 
1469196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1470352f7f91STakashi Iwai 	if (!path)
1471352f7f91STakashi Iwai 		return 0;
1472352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1473352f7f91STakashi Iwai 	if (err < 0)
1474352f7f91STakashi Iwai 		return err;
1475352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1476352f7f91STakashi Iwai 	if (err < 0)
1477352f7f91STakashi Iwai 		return err;
1478352f7f91STakashi Iwai 	return 0;
1479352f7f91STakashi Iwai }
1480352f7f91STakashi Iwai 
1481352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1482352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1483196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1484352f7f91STakashi Iwai {
1485c2c80383STakashi Iwai 	int i;
1486352f7f91STakashi Iwai 
1487352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1488c2c80383STakashi Iwai 		const char *name;
1489c2c80383STakashi Iwai 		char tmp[44];
1490c2c80383STakashi Iwai 		int err, idx = 0;
1491c2c80383STakashi Iwai 
1492c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1493c2c80383STakashi Iwai 			name = "Bass Speaker";
1494c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1495c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1496352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1497c2c80383STakashi Iwai 			name = tmp;
1498352f7f91STakashi Iwai 		} else {
1499c2c80383STakashi Iwai 			name = pfx;
1500c2c80383STakashi Iwai 			idx = i;
1501352f7f91STakashi Iwai 		}
1502c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1503352f7f91STakashi Iwai 		if (err < 0)
1504352f7f91STakashi Iwai 			return err;
1505352f7f91STakashi Iwai 	}
1506352f7f91STakashi Iwai 	return 0;
1507352f7f91STakashi Iwai }
1508352f7f91STakashi Iwai 
1509352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1510352f7f91STakashi Iwai {
1511352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1512352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1513196c1766STakashi Iwai 				 spec->hp_paths,
1514352f7f91STakashi Iwai 				 "Headphone");
1515352f7f91STakashi Iwai }
1516352f7f91STakashi Iwai 
1517352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1518352f7f91STakashi Iwai {
1519352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1520352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1521196c1766STakashi Iwai 				 spec->speaker_paths,
1522352f7f91STakashi Iwai 				 "Speaker");
1523352f7f91STakashi Iwai }
1524352f7f91STakashi Iwai 
1525352f7f91STakashi Iwai /*
152638cf6f1aSTakashi Iwai  * independent HP controls
152738cf6f1aSTakashi Iwai  */
152838cf6f1aSTakashi Iwai 
152938cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
153038cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
153138cf6f1aSTakashi Iwai {
153238cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
153338cf6f1aSTakashi Iwai }
153438cf6f1aSTakashi Iwai 
153538cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
153638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
153738cf6f1aSTakashi Iwai {
153838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
153938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
154038cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
154138cf6f1aSTakashi Iwai 	return 0;
154238cf6f1aSTakashi Iwai }
154338cf6f1aSTakashi Iwai 
154438cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
154538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
154638cf6f1aSTakashi Iwai {
154738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
154838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
154938cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
155038cf6f1aSTakashi Iwai 	int ret = 0;
155138cf6f1aSTakashi Iwai 
155238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
155338cf6f1aSTakashi Iwai 	if (spec->active_streams) {
155438cf6f1aSTakashi Iwai 		ret = -EBUSY;
155538cf6f1aSTakashi Iwai 		goto unlock;
155638cf6f1aSTakashi Iwai 	}
155738cf6f1aSTakashi Iwai 
155838cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
155938cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
156038cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
156138cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
156238cf6f1aSTakashi Iwai 		else
156338cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
156438cf6f1aSTakashi Iwai 		ret = 1;
156538cf6f1aSTakashi Iwai 	}
156638cf6f1aSTakashi Iwai  unlock:
156738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
156838cf6f1aSTakashi Iwai 	return ret;
156938cf6f1aSTakashi Iwai }
157038cf6f1aSTakashi Iwai 
157138cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
157238cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
157338cf6f1aSTakashi Iwai 	.name = "Independent HP",
157438cf6f1aSTakashi Iwai 	.info = indep_hp_info,
157538cf6f1aSTakashi Iwai 	.get = indep_hp_get,
157638cf6f1aSTakashi Iwai 	.put = indep_hp_put,
157738cf6f1aSTakashi Iwai };
157838cf6f1aSTakashi Iwai 
157938cf6f1aSTakashi Iwai 
158038cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
158138cf6f1aSTakashi Iwai {
158238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
158338cf6f1aSTakashi Iwai 
158438cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
158538cf6f1aSTakashi Iwai 		return 0;
158638cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
158738cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
158838cf6f1aSTakashi Iwai 		return 0;
158938cf6f1aSTakashi Iwai 	}
159038cf6f1aSTakashi Iwai 
159138cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
159238cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
159338cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
159438cf6f1aSTakashi Iwai 		return -ENOMEM;
159538cf6f1aSTakashi Iwai 	return 0;
159638cf6f1aSTakashi Iwai }
159738cf6f1aSTakashi Iwai 
159838cf6f1aSTakashi Iwai /*
1599352f7f91STakashi Iwai  * channel mode enum control
1600352f7f91STakashi Iwai  */
1601352f7f91STakashi Iwai 
1602352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1603352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1604352f7f91STakashi Iwai {
1605352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1606352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1607352f7f91STakashi Iwai 
1608352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1609352f7f91STakashi Iwai 	uinfo->count = 1;
1610352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1611352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1612352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1613352f7f91STakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch",
1614352f7f91STakashi Iwai 		(uinfo->value.enumerated.item + 1) * 2);
1615352f7f91STakashi Iwai 	return 0;
1616352f7f91STakashi Iwai }
1617352f7f91STakashi Iwai 
1618352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1619352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1620352f7f91STakashi Iwai {
1621352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1622352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1623352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
1624352f7f91STakashi Iwai 	return 0;
1625352f7f91STakashi Iwai }
1626352f7f91STakashi Iwai 
1627196c1766STakashi Iwai static inline struct nid_path *
1628196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1629196c1766STakashi Iwai {
1630196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1631196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1632196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1633196c1766STakashi Iwai }
1634196c1766STakashi Iwai 
1635352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1636352f7f91STakashi Iwai {
1637352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1638352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1639352f7f91STakashi Iwai 	struct nid_path *path;
1640352f7f91STakashi Iwai 
1641196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1642352f7f91STakashi Iwai 	if (!path)
1643352f7f91STakashi Iwai 		return -EINVAL;
1644352f7f91STakashi Iwai 
1645352f7f91STakashi Iwai 	if (path->active == output)
1646352f7f91STakashi Iwai 		return 0;
1647352f7f91STakashi Iwai 
1648352f7f91STakashi Iwai 	if (output) {
1649352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
1650352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1651d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1652352f7f91STakashi Iwai 	} else {
1653d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1654352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
1655352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid,
1656352f7f91STakashi Iwai 					  spec->multi_io[idx].ctl_in);
1657352f7f91STakashi Iwai 	}
1658352f7f91STakashi Iwai 	return 0;
1659352f7f91STakashi Iwai }
1660352f7f91STakashi Iwai 
1661352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1662352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1663352f7f91STakashi Iwai {
1664352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1665352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1666352f7f91STakashi Iwai 	int i, ch;
1667352f7f91STakashi Iwai 
1668352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1669352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1670352f7f91STakashi Iwai 		return -EINVAL;
1671352f7f91STakashi Iwai 	if (ch == (spec->ext_channel_count - 1) / 2)
1672352f7f91STakashi Iwai 		return 0;
1673352f7f91STakashi Iwai 	spec->ext_channel_count = (ch + 1) * 2;
1674352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1675352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1676352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1677352f7f91STakashi Iwai 					  spec->const_channel_count);
1678352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1679352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1680352f7f91STakashi Iwai 	return 1;
1681352f7f91STakashi Iwai }
1682352f7f91STakashi Iwai 
1683352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1684352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1685352f7f91STakashi Iwai 	.name = "Channel Mode",
1686352f7f91STakashi Iwai 	.info = ch_mode_info,
1687352f7f91STakashi Iwai 	.get = ch_mode_get,
1688352f7f91STakashi Iwai 	.put = ch_mode_put,
1689352f7f91STakashi Iwai };
1690352f7f91STakashi Iwai 
1691352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1692352f7f91STakashi Iwai {
1693352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1694352f7f91STakashi Iwai 
1695352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
169612c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1697352f7f91STakashi Iwai 			return -ENOMEM;
1698352f7f91STakashi Iwai 	}
1699352f7f91STakashi Iwai 	return 0;
1700352f7f91STakashi Iwai }
1701352f7f91STakashi Iwai 
1702352f7f91STakashi Iwai /*
1703c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1704c30aa7b2STakashi Iwai  */
1705c30aa7b2STakashi Iwai 
1706c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1707c30aa7b2STakashi Iwai 
1708c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1709c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1710c30aa7b2STakashi Iwai {
1711c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1712c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1713c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1714c30aa7b2STakashi Iwai 	return 0;
1715c30aa7b2STakashi Iwai }
1716c30aa7b2STakashi Iwai 
1717c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1718c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1719c30aa7b2STakashi Iwai {
1720c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1721c30aa7b2STakashi Iwai 
1722c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1723c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1724c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1725c30aa7b2STakashi Iwai 		return;
1726c30aa7b2STakashi Iwai 	if (do_mix) {
1727c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1728c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1729c30aa7b2STakashi Iwai 	} else {
1730c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1731c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1732c30aa7b2STakashi Iwai 	}
1733c30aa7b2STakashi Iwai }
1734c30aa7b2STakashi Iwai 
1735c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1736c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1737c30aa7b2STakashi Iwai {
1738c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1739c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1740c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
1741c30aa7b2STakashi Iwai 
1742c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
1743c30aa7b2STakashi Iwai 		return 0;
1744c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
1745c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
1746c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
1747c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
1748c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
1749c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
1750c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
1751c30aa7b2STakashi Iwai 	return 1;
1752c30aa7b2STakashi Iwai }
1753c30aa7b2STakashi Iwai 
1754c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
1755c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1756c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
1757c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
1758c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
1759c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
1760c30aa7b2STakashi Iwai };
1761c30aa7b2STakashi Iwai 
1762c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
1763c30aa7b2STakashi Iwai {
1764c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1765c30aa7b2STakashi Iwai 
1766c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
1767c30aa7b2STakashi Iwai 		return 0;
1768c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1769c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
1770c30aa7b2STakashi Iwai 		return 0;
1771c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
1772c30aa7b2STakashi Iwai 		return -ENOMEM;
1773c30aa7b2STakashi Iwai 	return 0;
1774c30aa7b2STakashi Iwai }
1775c30aa7b2STakashi Iwai 
1776c30aa7b2STakashi Iwai /*
1777352f7f91STakashi Iwai  * shared headphone/mic handling
1778352f7f91STakashi Iwai  */
1779352f7f91STakashi Iwai 
1780352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
1781352f7f91STakashi Iwai 
1782352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
1783352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
1784352f7f91STakashi Iwai {
1785352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1786352f7f91STakashi Iwai 	unsigned int val;
1787352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
1788352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
1789352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
1790352f7f91STakashi Iwai 	 */
1791352f7f91STakashi Iwai 
1792352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
1793352f7f91STakashi Iwai 
1794352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
1795352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
1796352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
1797352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
1798352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
1799352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
18007594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
18017594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
1802352f7f91STakashi Iwai 	}
1803352f7f91STakashi Iwai 
1804352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
18057594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, val);
1806352f7f91STakashi Iwai 
1807352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
1808352f7f91STakashi Iwai 	call_update_outputs(codec);
1809352f7f91STakashi Iwai }
1810352f7f91STakashi Iwai 
1811352f7f91STakashi Iwai /* create a shared input with the headphone out */
1812352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
1813352f7f91STakashi Iwai {
1814352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1815352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1816352f7f91STakashi Iwai 	unsigned int defcfg;
1817352f7f91STakashi Iwai 	hda_nid_t nid;
1818352f7f91STakashi Iwai 
1819352f7f91STakashi Iwai 	/* only one internal input pin? */
1820352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
1821352f7f91STakashi Iwai 		return 0;
1822352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
1823352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
1824352f7f91STakashi Iwai 		return 0;
1825352f7f91STakashi Iwai 
1826352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1827352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
1828352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
1829352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
1830352f7f91STakashi Iwai 	else
1831352f7f91STakashi Iwai 		return 0; /* both not available */
1832352f7f91STakashi Iwai 
1833352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
1834352f7f91STakashi Iwai 		return 0; /* no input */
1835352f7f91STakashi Iwai 
1836352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
1837352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
1838352f7f91STakashi Iwai 	cfg->num_inputs = 2;
1839352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
1840352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
1841352f7f91STakashi Iwai 	return 0;
1842352f7f91STakashi Iwai }
1843352f7f91STakashi Iwai 
1844352f7f91STakashi Iwai 
1845352f7f91STakashi Iwai /*
1846352f7f91STakashi Iwai  * Parse input paths
1847352f7f91STakashi Iwai  */
1848352f7f91STakashi Iwai 
1849352f7f91STakashi Iwai #ifdef CONFIG_PM
1850352f7f91STakashi Iwai /* add the powersave loopback-list entry */
1851352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
1852352f7f91STakashi Iwai {
1853352f7f91STakashi Iwai 	struct hda_amp_list *list;
1854352f7f91STakashi Iwai 
1855352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
1856352f7f91STakashi Iwai 		return;
1857352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
1858352f7f91STakashi Iwai 	list->nid = mix;
1859352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
1860352f7f91STakashi Iwai 	list->idx = idx;
1861352f7f91STakashi Iwai 	spec->num_loopbacks++;
1862cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
1863cb53c626STakashi Iwai }
1864cb53c626STakashi Iwai #else
1865352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
1866cb53c626STakashi Iwai #endif
1867cb53c626STakashi Iwai 
1868352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
1869196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
1870196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
1871352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
18721da177e4SLinus Torvalds {
1873352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1874352f7f91STakashi Iwai 	struct nid_path *path;
1875352f7f91STakashi Iwai 	unsigned int val;
1876352f7f91STakashi Iwai 	int err, idx;
18771da177e4SLinus Torvalds 
1878352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
1879352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
1880352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
1881352f7f91STakashi Iwai 
18824ac0eefaSTakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, HDA_PARSE_ALL);
1883352f7f91STakashi Iwai 	if (!path)
1884352f7f91STakashi Iwai 		return -EINVAL;
18850c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
1886196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
1887352f7f91STakashi Iwai 
1888352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
1889352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
1890352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1891352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
1892d13bd412STakashi Iwai 		if (err < 0)
18931da177e4SLinus Torvalds 			return err;
1894352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
18951da177e4SLinus Torvalds 	}
18961da177e4SLinus Torvalds 
1897352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
1898352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1899352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
1900d13bd412STakashi Iwai 		if (err < 0)
19011da177e4SLinus Torvalds 			return err;
1902352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
19031da177e4SLinus Torvalds 	}
19041da177e4SLinus Torvalds 
1905352f7f91STakashi Iwai 	path->active = true;
1906352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
1907352f7f91STakashi Iwai 	return 0;
19081da177e4SLinus Torvalds }
19091da177e4SLinus Torvalds 
1910352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
19111da177e4SLinus Torvalds {
1912352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
1913352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
1914352f7f91STakashi Iwai }
1915352f7f91STakashi Iwai 
1916352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
1917352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
1918352f7f91STakashi Iwai {
1919352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1920352f7f91STakashi Iwai 	hda_nid_t nid;
1921352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
1922352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
1923352f7f91STakashi Iwai 	int i, nums = 0;
1924352f7f91STakashi Iwai 
1925352f7f91STakashi Iwai 	nid = codec->start_nid;
1926352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1927352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
1928352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
1929352f7f91STakashi Iwai 
1930352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
1931352f7f91STakashi Iwai 			continue;
1932352f7f91STakashi Iwai 		adc_nids[nums] = nid;
1933352f7f91STakashi Iwai 		if (++nums >= max_nums)
1934352f7f91STakashi Iwai 			break;
1935352f7f91STakashi Iwai 	}
1936352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
1937352f7f91STakashi Iwai 	return nums;
1938352f7f91STakashi Iwai }
1939352f7f91STakashi Iwai 
1940352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
1941352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
1942352f7f91STakashi Iwai  */
1943352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
1944352f7f91STakashi Iwai {
1945352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1946352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
1947352f7f91STakashi Iwai 	hda_nid_t adc_nids[ARRAY_SIZE(spec->adc_nids)];
1948352f7f91STakashi Iwai 	int i, n, nums;
1949352f7f91STakashi Iwai 	hda_nid_t pin, adc;
1950352f7f91STakashi Iwai 
1951352f7f91STakashi Iwai  again:
1952352f7f91STakashi Iwai 	nums = 0;
1953352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
1954352f7f91STakashi Iwai 		adc = spec->adc_nids[n];
1955352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1956352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1957352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
1958352f7f91STakashi Iwai 				break;
1959352f7f91STakashi Iwai 		}
1960352f7f91STakashi Iwai 		if (i >= imux->num_items)
1961352f7f91STakashi Iwai 			adc_nids[nums++] = adc;
1962352f7f91STakashi Iwai 	}
1963352f7f91STakashi Iwai 
1964352f7f91STakashi Iwai 	if (!nums) {
1965352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
1966352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
1967352f7f91STakashi Iwai 			imux->num_items = 1;
1968352f7f91STakashi Iwai 			goto again;
1969352f7f91STakashi Iwai 		}
1970352f7f91STakashi Iwai 
1971352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
1972352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1973352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1974352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
1975352f7f91STakashi Iwai 				adc = spec->adc_nids[n];
1976352f7f91STakashi Iwai 				if (is_reachable_path(codec, pin, adc)) {
1977352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
1978352f7f91STakashi Iwai 					break;
1979352f7f91STakashi Iwai 				}
1980352f7f91STakashi Iwai 			}
1981352f7f91STakashi Iwai 		}
1982352f7f91STakashi Iwai 
1983352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
1984352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
1985352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
1986352f7f91STakashi Iwai 		memcpy(spec->adc_nids, adc_nids, nums * sizeof(hda_nid_t));
1987352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
1988352f7f91STakashi Iwai 	}
1989352f7f91STakashi Iwai 
1990352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
1991352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
1992352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
1993352f7f91STakashi Iwai 	}
1994352f7f91STakashi Iwai 
1995352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
1996352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
1997352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
1998352f7f91STakashi Iwai 
19991da177e4SLinus Torvalds 	return 0;
20001da177e4SLinus Torvalds }
20011da177e4SLinus Torvalds 
20021da177e4SLinus Torvalds /*
2003352f7f91STakashi Iwai  * create playback/capture controls for input pins
20041da177e4SLinus Torvalds  */
2005352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2006a7da6ce5STakashi Iwai {
2007352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2008352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2009352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2010352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2011352f7f91STakashi Iwai 	int num_adcs;
2012352f7f91STakashi Iwai 	int i, c, err, type_idx = 0;
2013352f7f91STakashi Iwai 	const char *prev_label = NULL;
2014a7da6ce5STakashi Iwai 
2015352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2016352f7f91STakashi Iwai 	if (num_adcs < 0)
2017352f7f91STakashi Iwai 		return 0;
2018352f7f91STakashi Iwai 
2019352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2020352f7f91STakashi Iwai 		hda_nid_t pin;
2021352f7f91STakashi Iwai 		const char *label;
2022352f7f91STakashi Iwai 		bool imux_added;
2023352f7f91STakashi Iwai 
2024352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2025352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2026352f7f91STakashi Iwai 			continue;
2027352f7f91STakashi Iwai 
2028352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2029352f7f91STakashi Iwai 		if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2030352f7f91STakashi Iwai 			label = "Headphone Mic";
2031352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2032352f7f91STakashi Iwai 			type_idx++;
2033352f7f91STakashi Iwai 		else
2034352f7f91STakashi Iwai 			type_idx = 0;
2035352f7f91STakashi Iwai 		prev_label = label;
2036352f7f91STakashi Iwai 
2037352f7f91STakashi Iwai 		if (mixer) {
2038352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2039196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2040352f7f91STakashi Iwai 						       label, type_idx, mixer);
2041a7da6ce5STakashi Iwai 				if (err < 0)
2042a7da6ce5STakashi Iwai 					return err;
2043a7da6ce5STakashi Iwai 			}
2044352f7f91STakashi Iwai 		}
2045352f7f91STakashi Iwai 
2046352f7f91STakashi Iwai 		imux_added = false;
2047352f7f91STakashi Iwai 		for (c = 0; c < num_adcs; c++) {
2048352f7f91STakashi Iwai 			struct nid_path *path;
2049352f7f91STakashi Iwai 			hda_nid_t adc = spec->adc_nids[c];
2050352f7f91STakashi Iwai 
2051352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
2052352f7f91STakashi Iwai 				continue;
2053352f7f91STakashi Iwai 			path = snd_array_new(&spec->paths);
2054352f7f91STakashi Iwai 			if (!path)
2055352f7f91STakashi Iwai 				return -ENOMEM;
2056352f7f91STakashi Iwai 			memset(path, 0, sizeof(*path));
20574ac0eefaSTakashi Iwai 			if (!snd_hda_parse_nid_path(codec, pin, adc, HDA_PARSE_ALL, path)) {
2058352f7f91STakashi Iwai 				snd_printd(KERN_ERR
2059352f7f91STakashi Iwai 					   "invalid input path 0x%x -> 0x%x\n",
2060352f7f91STakashi Iwai 					   pin, adc);
2061352f7f91STakashi Iwai 				spec->paths.used--;
2062352f7f91STakashi Iwai 				continue;
2063352f7f91STakashi Iwai 			}
20640c8c0f56STakashi Iwai 			print_nid_path("input", path);
2065352f7f91STakashi Iwai 
2066352f7f91STakashi Iwai 			if (!imux_added) {
2067352f7f91STakashi Iwai 				spec->imux_pins[imux->num_items] = pin;
2068352f7f91STakashi Iwai 				snd_hda_add_imux_item(imux, label,
2069352f7f91STakashi Iwai 						      imux->num_items, NULL);
2070352f7f91STakashi Iwai 				imux_added = true;
2071352f7f91STakashi Iwai 			}
2072352f7f91STakashi Iwai 		}
2073352f7f91STakashi Iwai 	}
2074352f7f91STakashi Iwai 
2075a7da6ce5STakashi Iwai 	return 0;
2076a7da6ce5STakashi Iwai }
2077a7da6ce5STakashi Iwai 
20781da177e4SLinus Torvalds 
2079352f7f91STakashi Iwai /*
2080352f7f91STakashi Iwai  * input source mux
2081352f7f91STakashi Iwai  */
2082352f7f91STakashi Iwai 
2083352f7f91STakashi Iwai /* get the ADC NID corresponding to the given index */
2084352f7f91STakashi Iwai static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
2085352f7f91STakashi Iwai {
2086352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2087352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2088352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2089352f7f91STakashi Iwai 	return spec->adc_nids[adc_idx];
209097ec558aSTakashi Iwai }
2091352f7f91STakashi Iwai 
2092352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2093352f7f91STakashi Iwai 		      unsigned int idx);
2094352f7f91STakashi Iwai 
2095352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2096352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2097352f7f91STakashi Iwai {
2098352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2099352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2100352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2101352f7f91STakashi Iwai }
2102352f7f91STakashi Iwai 
2103352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2104352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2105352f7f91STakashi Iwai {
2106352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2107352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2108352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2109352f7f91STakashi Iwai 
2110352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
21111da177e4SLinus Torvalds 	return 0;
21121da177e4SLinus Torvalds }
21131da177e4SLinus Torvalds 
2114352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2115352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
21161da177e4SLinus Torvalds {
2117352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2118352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2119352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2120352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2121352f7f91STakashi Iwai }
2122352f7f91STakashi Iwai 
2123352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
21241da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2125352f7f91STakashi Iwai 	.name = "Input Source",
2126352f7f91STakashi Iwai 	.info = mux_enum_info,
2127352f7f91STakashi Iwai 	.get = mux_enum_get,
2128352f7f91STakashi Iwai 	.put = mux_enum_put,
21291da177e4SLinus Torvalds };
2130071c73adSTakashi Iwai 
213147d46abbSTakashi Iwai /*
213247d46abbSTakashi Iwai  * capture volume and capture switch ctls
213347d46abbSTakashi Iwai  */
213447d46abbSTakashi Iwai 
2135352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2136352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2137071c73adSTakashi Iwai 
213847d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2139352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2140352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2141352f7f91STakashi Iwai 			  put_call_t func, int type)
2142352f7f91STakashi Iwai {
2143352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2144352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2145352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2146352f7f91STakashi Iwai 	struct nid_path *path;
2147352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2148071c73adSTakashi Iwai 
2149352f7f91STakashi Iwai 	imux = &spec->input_mux;
2150352f7f91STakashi Iwai 	adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
2151352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
215247d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
215347d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
215447d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
215547d46abbSTakashi Iwai 	 */
2156352f7f91STakashi Iwai 	codec->cached_write = 1;
2157352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2158352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2159352f7f91STakashi Iwai 					    get_adc_nid(codec, adc_idx, i));
2160352f7f91STakashi Iwai 		if (!path->ctls[type])
2161352f7f91STakashi Iwai 			continue;
2162352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2163352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2164352f7f91STakashi Iwai 		if (err < 0)
2165352f7f91STakashi Iwai 			goto error;
2166352f7f91STakashi Iwai 	}
2167352f7f91STakashi Iwai  error:
2168352f7f91STakashi Iwai 	codec->cached_write = 0;
2169352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
217047d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2171352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2172352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
2173352f7f91STakashi Iwai 	return err;
2174352f7f91STakashi Iwai }
2175352f7f91STakashi Iwai 
2176352f7f91STakashi Iwai /* capture volume ctl callbacks */
2177352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2178352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2179352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2180352f7f91STakashi Iwai 
2181352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2182352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2183352f7f91STakashi Iwai {
2184352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2185352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2186352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2187352f7f91STakashi Iwai }
2188352f7f91STakashi Iwai 
2189352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2190352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2191352f7f91STakashi Iwai 	.name = "Capture Volume",
2192352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2193352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2194352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2195352f7f91STakashi Iwai 	.info = cap_vol_info,
2196352f7f91STakashi Iwai 	.get = cap_vol_get,
2197352f7f91STakashi Iwai 	.put = cap_vol_put,
2198352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2199352f7f91STakashi Iwai };
2200352f7f91STakashi Iwai 
2201352f7f91STakashi Iwai /* capture switch ctl callbacks */
2202352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2203352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2204352f7f91STakashi Iwai 
2205352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2206352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2207352f7f91STakashi Iwai {
2208352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2209352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2210352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2211352f7f91STakashi Iwai }
2212352f7f91STakashi Iwai 
2213352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2214352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2215352f7f91STakashi Iwai 	.name = "Capture Switch",
2216352f7f91STakashi Iwai 	.info = cap_sw_info,
2217352f7f91STakashi Iwai 	.get = cap_sw_get,
2218352f7f91STakashi Iwai 	.put = cap_sw_put,
2219352f7f91STakashi Iwai };
2220352f7f91STakashi Iwai 
2221352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2222352f7f91STakashi Iwai {
2223352f7f91STakashi Iwai 	hda_nid_t nid;
2224352f7f91STakashi Iwai 	int i, depth;
2225352f7f91STakashi Iwai 
2226352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2227352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2228352f7f91STakashi Iwai 		if (depth >= path->depth)
2229352f7f91STakashi Iwai 			return -EINVAL;
2230352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2231352f7f91STakashi Iwai 		nid = path->path[i];
2232352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2233352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2234352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2235352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2236352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2237352f7f91STakashi Iwai 				int idx = path->idx[i];
2238352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2239352f7f91STakashi Iwai 					idx = 0;
2240352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2241352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2242352f7f91STakashi Iwai 			}
2243352f7f91STakashi Iwai 		}
2244352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2245352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2246352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2247352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2248352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2249352f7f91STakashi Iwai 				int idx = path->idx[i];
2250352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2251352f7f91STakashi Iwai 					idx = 0;
2252352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2253352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2254352f7f91STakashi Iwai 			}
2255352f7f91STakashi Iwai 		}
2256352f7f91STakashi Iwai 	}
2257352f7f91STakashi Iwai 	return 0;
2258352f7f91STakashi Iwai }
2259352f7f91STakashi Iwai 
2260352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2261352f7f91STakashi Iwai {
2262352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2263352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2264352f7f91STakashi Iwai 	unsigned int val;
2265352f7f91STakashi Iwai 	int i;
2266352f7f91STakashi Iwai 
2267352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2268352f7f91STakashi Iwai 		return false;
2269352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2270352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2271352f7f91STakashi Iwai 			continue;
2272352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2273352f7f91STakashi Iwai 			return false;
2274352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2275352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2276352f7f91STakashi Iwai 	}
2277352f7f91STakashi Iwai 	return false;
2278352f7f91STakashi Iwai }
2279352f7f91STakashi Iwai 
2280352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2281352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2282352f7f91STakashi Iwai 			      bool inv_dmic)
2283352f7f91STakashi Iwai {
2284352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2285352f7f91STakashi Iwai 	char tmpname[44];
2286352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2287352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2288352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2289352f7f91STakashi Iwai 	int err;
2290352f7f91STakashi Iwai 
2291352f7f91STakashi Iwai 	if (!ctl)
2292352f7f91STakashi Iwai 		return 0;
2293352f7f91STakashi Iwai 
2294352f7f91STakashi Iwai 	if (label)
2295352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2296352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2297352f7f91STakashi Iwai 	else
2298352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2299352f7f91STakashi Iwai 			 "Capture %s", sfx);
2300352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2301352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2302352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2303352f7f91STakashi Iwai 		return err;
2304352f7f91STakashi Iwai 
2305352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2306352f7f91STakashi Iwai 	if (label)
2307352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2308352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2309352f7f91STakashi Iwai 	else
2310352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2311352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2312352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2313352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2314352f7f91STakashi Iwai }
2315352f7f91STakashi Iwai 
2316352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2317352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2318352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2319352f7f91STakashi Iwai 				     bool inv_dmic)
2320352f7f91STakashi Iwai {
2321352f7f91STakashi Iwai 	int err;
2322352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2323352f7f91STakashi Iwai 	if (err < 0)
2324352f7f91STakashi Iwai 		return err;
2325352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2326071c73adSTakashi Iwai 	if (err < 0)
2327071c73adSTakashi Iwai 		return err;
2328071c73adSTakashi Iwai 	return 0;
23291da177e4SLinus Torvalds }
2330071c73adSTakashi Iwai 
2331352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2332352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2333352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2334352f7f91STakashi Iwai {
2335352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2336352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2337352f7f91STakashi Iwai 
2338352f7f91STakashi Iwai 	if (vol_ctl) {
233912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2340352f7f91STakashi Iwai 		if (!knew)
2341352f7f91STakashi Iwai 			return -ENOMEM;
2342352f7f91STakashi Iwai 		knew->index = idx;
2343352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2344352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2345352f7f91STakashi Iwai 	}
2346352f7f91STakashi Iwai 	if (sw_ctl) {
234712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2348352f7f91STakashi Iwai 		if (!knew)
2349352f7f91STakashi Iwai 			return -ENOMEM;
2350352f7f91STakashi Iwai 		knew->index = idx;
2351352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2352352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2353352f7f91STakashi Iwai 	}
2354352f7f91STakashi Iwai 	return 0;
2355352f7f91STakashi Iwai }
2356352f7f91STakashi Iwai 
2357352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2358352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2359352f7f91STakashi Iwai {
2360352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2361352f7f91STakashi Iwai 	struct nid_path *path;
2362352f7f91STakashi Iwai 	unsigned int ctl;
2363352f7f91STakashi Iwai 	int i;
2364352f7f91STakashi Iwai 
2365352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2366352f7f91STakashi Iwai 				    get_adc_nid(codec, 0, idx));
2367352f7f91STakashi Iwai 	if (!path)
2368352f7f91STakashi Iwai 		return 0;
2369352f7f91STakashi Iwai 	ctl = path->ctls[type];
2370352f7f91STakashi Iwai 	if (!ctl)
2371352f7f91STakashi Iwai 		return 0;
2372352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2373352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2374352f7f91STakashi Iwai 					    get_adc_nid(codec, 0, i));
2375352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2376352f7f91STakashi Iwai 			return 0;
2377352f7f91STakashi Iwai 	}
2378352f7f91STakashi Iwai 	return ctl;
2379352f7f91STakashi Iwai }
2380352f7f91STakashi Iwai 
2381352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2382352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2383352f7f91STakashi Iwai {
2384352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2385352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2386352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2387352f7f91STakashi Iwai 	const char *prev_label = NULL;
2388352f7f91STakashi Iwai 
2389352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2390352f7f91STakashi Iwai 		const char *label;
2391352f7f91STakashi Iwai 		bool inv_dmic;
2392352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
2393352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2394352f7f91STakashi Iwai 			type_idx++;
2395352f7f91STakashi Iwai 		else
2396352f7f91STakashi Iwai 			type_idx = 0;
2397352f7f91STakashi Iwai 		prev_label = label;
2398352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2399352f7f91STakashi Iwai 
2400352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2401352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2402352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2403352f7f91STakashi Iwai 						 inv_dmic);
2404d13bd412STakashi Iwai 			if (err < 0)
2405071c73adSTakashi Iwai 				return err;
2406352f7f91STakashi Iwai 		}
2407352f7f91STakashi Iwai 	}
2408071c73adSTakashi Iwai 	return 0;
2409352f7f91STakashi Iwai }
2410071c73adSTakashi Iwai 
2411352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2412352f7f91STakashi Iwai {
2413352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2414352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2415352f7f91STakashi Iwai 	int i, n, nums, err;
2416352f7f91STakashi Iwai 
2417352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2418352f7f91STakashi Iwai 		nums = 1;
2419352f7f91STakashi Iwai 	else
2420352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2421352f7f91STakashi Iwai 
2422352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2423352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2424624d914dSTakashi Iwai 		const char *name;
2425624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2426624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2427352f7f91STakashi Iwai 		if (!knew)
2428352f7f91STakashi Iwai 			return -ENOMEM;
2429352f7f91STakashi Iwai 		knew->count = nums;
2430352f7f91STakashi Iwai 	}
2431352f7f91STakashi Iwai 
2432352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2433352f7f91STakashi Iwai 		bool multi = false;
2434352f7f91STakashi Iwai 		bool inv_dmic = false;
2435352f7f91STakashi Iwai 		int vol, sw;
2436352f7f91STakashi Iwai 
2437352f7f91STakashi Iwai 		vol = sw = 0;
2438352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2439352f7f91STakashi Iwai 			struct nid_path *path;
2440352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2441352f7f91STakashi Iwai 						    get_adc_nid(codec, n, i));
2442352f7f91STakashi Iwai 			if (!path)
2443352f7f91STakashi Iwai 				continue;
2444352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2445352f7f91STakashi Iwai 			if (!vol)
2446352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
2447352f7f91STakashi Iwai 			else if (vol != path->ctls[NID_PATH_VOL_CTL])
2448352f7f91STakashi Iwai 				multi = true;
2449352f7f91STakashi Iwai 			if (!sw)
2450352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
2451352f7f91STakashi Iwai 			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
2452352f7f91STakashi Iwai 				multi = true;
2453352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2454352f7f91STakashi Iwai 				inv_dmic = true;
2455352f7f91STakashi Iwai 		}
2456352f7f91STakashi Iwai 
2457352f7f91STakashi Iwai 		if (!multi)
2458352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2459352f7f91STakashi Iwai 							inv_dmic);
2460352f7f91STakashi Iwai 		else if (!spec->multi_cap_vol)
2461352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2462352f7f91STakashi Iwai 		else
2463352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
2464d13bd412STakashi Iwai 		if (err < 0)
2465071c73adSTakashi Iwai 			return err;
2466071c73adSTakashi Iwai 	}
2467071c73adSTakashi Iwai 
24681da177e4SLinus Torvalds 	return 0;
24691da177e4SLinus Torvalds }
24701da177e4SLinus Torvalds 
2471352f7f91STakashi Iwai /*
2472352f7f91STakashi Iwai  * add mic boosts if needed
2473352f7f91STakashi Iwai  */
2474352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
2475352f7f91STakashi Iwai {
2476352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2477352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2478352f7f91STakashi Iwai 	int i, err;
2479352f7f91STakashi Iwai 	int type_idx = 0;
2480352f7f91STakashi Iwai 	hda_nid_t nid;
2481352f7f91STakashi Iwai 	const char *prev_label = NULL;
2482352f7f91STakashi Iwai 
2483352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2484352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
2485352f7f91STakashi Iwai 			break;
2486352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
2487352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
2488352f7f91STakashi Iwai 			const char *label;
24895abd4888STakashi Iwai 			char boost_label[44];
2490352f7f91STakashi Iwai 			struct nid_path *path;
2491352f7f91STakashi Iwai 			unsigned int val;
2492352f7f91STakashi Iwai 
2493352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
2494352f7f91STakashi Iwai 			if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2495352f7f91STakashi Iwai 				label = "Headphone Mic";
2496352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
2497352f7f91STakashi Iwai 				type_idx++;
2498352f7f91STakashi Iwai 			else
2499352f7f91STakashi Iwai 				type_idx = 0;
2500352f7f91STakashi Iwai 			prev_label = label;
2501352f7f91STakashi Iwai 
2502352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
2503352f7f91STakashi Iwai 				 "%s Boost Volume", label);
2504352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
2505352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
2506352f7f91STakashi Iwai 					  boost_label, type_idx, val);
2507352f7f91STakashi Iwai 			if (err < 0)
2508352f7f91STakashi Iwai 				return err;
2509352f7f91STakashi Iwai 
2510352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
2511352f7f91STakashi Iwai 			if (path)
2512352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
2513352f7f91STakashi Iwai 		}
2514352f7f91STakashi Iwai 	}
2515352f7f91STakashi Iwai 	return 0;
2516352f7f91STakashi Iwai }
2517352f7f91STakashi Iwai 
2518352f7f91STakashi Iwai /*
2519352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
2520352f7f91STakashi Iwai  */
2521352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
2522352f7f91STakashi Iwai {
2523352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
25240c8c0f56STakashi Iwai 	struct nid_path *path;
2525352f7f91STakashi Iwai 	int i, nums;
2526352f7f91STakashi Iwai 	hda_nid_t dig_nid;
2527352f7f91STakashi Iwai 
2528352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
2529352f7f91STakashi Iwai 	nums = 0;
2530352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
2531352f7f91STakashi Iwai 		hda_nid_t pin = spec->autocfg.dig_out_pins[i];
2532352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
2533352f7f91STakashi Iwai 		if (!dig_nid)
2534352f7f91STakashi Iwai 			continue;
25354ac0eefaSTakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, HDA_PARSE_ALL);
25360c8c0f56STakashi Iwai 		if (!path)
2537352f7f91STakashi Iwai 			continue;
25380c8c0f56STakashi Iwai 		print_nid_path("digout", path);
2539e1284af7STakashi Iwai 		path->active = true;
2540196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
2541352f7f91STakashi Iwai 		if (!nums) {
2542352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
2543352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
2544352f7f91STakashi Iwai 		} else {
2545352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2546352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2547352f7f91STakashi Iwai 			break;
2548352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
2549352f7f91STakashi Iwai 		}
2550352f7f91STakashi Iwai 		nums++;
2551352f7f91STakashi Iwai 	}
2552352f7f91STakashi Iwai 
2553352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
2554352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
2555352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2556352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
2557352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2558352f7f91STakashi Iwai 				continue;
2559352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
2560352f7f91STakashi Iwai 				continue;
2561352f7f91STakashi Iwai 			path = snd_hda_add_new_path(codec,
2562352f7f91STakashi Iwai 						    spec->autocfg.dig_in_pin,
25634ac0eefaSTakashi Iwai 						    dig_nid, HDA_PARSE_ALL);
2564352f7f91STakashi Iwai 			if (path) {
25650c8c0f56STakashi Iwai 				print_nid_path("digin", path);
2566352f7f91STakashi Iwai 				path->active = true;
2567352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
25682430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
2569352f7f91STakashi Iwai 				break;
2570352f7f91STakashi Iwai 			}
2571352f7f91STakashi Iwai 		}
2572352f7f91STakashi Iwai 	}
2573352f7f91STakashi Iwai }
2574352f7f91STakashi Iwai 
25751da177e4SLinus Torvalds 
25761da177e4SLinus Torvalds /*
2577352f7f91STakashi Iwai  * input MUX handling
25781da177e4SLinus Torvalds  */
25791da177e4SLinus Torvalds 
2580352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
2581352f7f91STakashi Iwai 
2582352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
2583352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2584352f7f91STakashi Iwai 		      unsigned int idx)
2585352f7f91STakashi Iwai {
2586352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2587352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2588352f7f91STakashi Iwai 	struct nid_path *path;
2589352f7f91STakashi Iwai 
2590352f7f91STakashi Iwai 	imux = &spec->input_mux;
2591352f7f91STakashi Iwai 	if (!imux->num_items)
25921da177e4SLinus Torvalds 		return 0;
25931da177e4SLinus Torvalds 
2594352f7f91STakashi Iwai 	if (idx >= imux->num_items)
2595352f7f91STakashi Iwai 		idx = imux->num_items - 1;
2596352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
2597352f7f91STakashi Iwai 		return 0;
2598352f7f91STakashi Iwai 
2599352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec,
2600352f7f91STakashi Iwai 				    spec->imux_pins[spec->cur_mux[adc_idx]],
2601352f7f91STakashi Iwai 				    spec->adc_nids[adc_idx]);
2602352f7f91STakashi Iwai 	if (!path)
2603352f7f91STakashi Iwai 		return 0;
2604352f7f91STakashi Iwai 	if (path->active)
2605352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
2606352f7f91STakashi Iwai 
2607352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
2608352f7f91STakashi Iwai 
2609352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
2610352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
2611352f7f91STakashi Iwai 
2612352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2613352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
2614352f7f91STakashi Iwai 
2615352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2616352f7f91STakashi Iwai 				    get_adc_nid(codec, adc_idx, idx));
2617352f7f91STakashi Iwai 	if (!path)
2618352f7f91STakashi Iwai 		return 0;
2619352f7f91STakashi Iwai 	if (path->active)
2620352f7f91STakashi Iwai 		return 0;
2621352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
2622352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
2623352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
26241da177e4SLinus Torvalds 	return 1;
26251da177e4SLinus Torvalds }
26261da177e4SLinus Torvalds 
26271da177e4SLinus Torvalds 
26281da177e4SLinus Torvalds /*
2629352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
26301da177e4SLinus Torvalds  */
2631352f7f91STakashi Iwai 
2632352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
2633352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
26341da177e4SLinus Torvalds {
2635352f7f91STakashi Iwai 	int i, present = 0;
26361da177e4SLinus Torvalds 
2637352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2638352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2639352f7f91STakashi Iwai 		if (!nid)
2640352f7f91STakashi Iwai 			break;
2641352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
26421da177e4SLinus Torvalds 	}
2643352f7f91STakashi Iwai 	return present;
26441da177e4SLinus Torvalds }
26451da177e4SLinus Torvalds 
2646352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
2647352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
2648352f7f91STakashi Iwai 			bool mute, bool hp_out)
26491da177e4SLinus Torvalds {
2650352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2651352f7f91STakashi Iwai 	unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
2652352f7f91STakashi Iwai 	int i;
26531da177e4SLinus Torvalds 
2654352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2655352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2656352f7f91STakashi Iwai 		unsigned int val;
2657352f7f91STakashi Iwai 		if (!nid)
2658352f7f91STakashi Iwai 			break;
2659352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
2660352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
2661352f7f91STakashi Iwai 		 */
2662352f7f91STakashi Iwai 		if (spec->keep_vref_in_automute) {
2663352f7f91STakashi Iwai 			val = snd_hda_codec_read(codec, nid, 0,
2664352f7f91STakashi Iwai 					AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2665352f7f91STakashi Iwai 			val &= ~PIN_HP;
2666352f7f91STakashi Iwai 		} else
2667352f7f91STakashi Iwai 			val = 0;
2668352f7f91STakashi Iwai 		val |= pin_bits;
26697594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, val);
2670d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
2671352f7f91STakashi Iwai 	}
2672352f7f91STakashi Iwai }
26731da177e4SLinus Torvalds 
2674352f7f91STakashi Iwai /* Toggle outputs muting */
26755d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
2676352f7f91STakashi Iwai {
2677352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2678352f7f91STakashi Iwai 	int on;
2679352f7f91STakashi Iwai 
2680352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
2681352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
2682352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
2683352f7f91STakashi Iwai 	 */
2684352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
2685352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2686352f7f91STakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute, true);
2687352f7f91STakashi Iwai 
2688352f7f91STakashi Iwai 	if (!spec->automute_speaker)
2689352f7f91STakashi Iwai 		on = 0;
2690352f7f91STakashi Iwai 	else
2691352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
2692352f7f91STakashi Iwai 	on |= spec->master_mute;
2693352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
2694352f7f91STakashi Iwai 		    spec->autocfg.speaker_pins, on, false);
2695352f7f91STakashi Iwai 
2696352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
2697352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
2698352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
2699352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
2700352f7f91STakashi Iwai 		return;
2701352f7f91STakashi Iwai 	if (!spec->automute_lo)
2702352f7f91STakashi Iwai 		on = 0;
2703352f7f91STakashi Iwai 	else
2704352f7f91STakashi Iwai 		on = spec->hp_jack_present;
2705352f7f91STakashi Iwai 	on |= spec->master_mute;
2706352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2707352f7f91STakashi Iwai 		    spec->autocfg.line_out_pins, on, false);
2708352f7f91STakashi Iwai }
27095d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
2710352f7f91STakashi Iwai 
2711352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
2712352f7f91STakashi Iwai {
2713352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2714352f7f91STakashi Iwai 	if (spec->automute_hook)
2715352f7f91STakashi Iwai 		spec->automute_hook(codec);
2716352f7f91STakashi Iwai 	else
27175d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
2718352f7f91STakashi Iwai }
2719352f7f91STakashi Iwai 
2720352f7f91STakashi Iwai /* standard HP-automute helper */
27215d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2722352f7f91STakashi Iwai {
2723352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2724352f7f91STakashi Iwai 
2725352f7f91STakashi Iwai 	spec->hp_jack_present =
2726352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2727352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
2728352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
2729352f7f91STakashi Iwai 		return;
2730352f7f91STakashi Iwai 	call_update_outputs(codec);
2731352f7f91STakashi Iwai }
27325d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
2733352f7f91STakashi Iwai 
2734352f7f91STakashi Iwai /* standard line-out-automute helper */
27355d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2736352f7f91STakashi Iwai {
2737352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2738352f7f91STakashi Iwai 
2739352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
2740352f7f91STakashi Iwai 		return;
2741352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
2742352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
2743352f7f91STakashi Iwai 		return;
2744352f7f91STakashi Iwai 
2745352f7f91STakashi Iwai 	spec->line_jack_present =
2746352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2747352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
2748352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
2749352f7f91STakashi Iwai 		return;
2750352f7f91STakashi Iwai 	call_update_outputs(codec);
2751352f7f91STakashi Iwai }
27525d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
2753352f7f91STakashi Iwai 
2754352f7f91STakashi Iwai /* standard mic auto-switch helper */
27555d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
2756352f7f91STakashi Iwai {
2757352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2758352f7f91STakashi Iwai 	int i;
2759352f7f91STakashi Iwai 
2760352f7f91STakashi Iwai 	if (!spec->auto_mic)
2761352f7f91STakashi Iwai 		return;
2762352f7f91STakashi Iwai 
2763352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
2764352f7f91STakashi Iwai 		if (snd_hda_jack_detect(codec, spec->am_entry[i].pin)) {
2765352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
2766352f7f91STakashi Iwai 			return;
2767352f7f91STakashi Iwai 		}
2768352f7f91STakashi Iwai 	}
2769352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
27701da177e4SLinus Torvalds }
27715d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
27721da177e4SLinus Torvalds 
27731da177e4SLinus Torvalds /*
2774352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
27751da177e4SLinus Torvalds  */
2776352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
2777352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2778352f7f91STakashi Iwai {
2779352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2780352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2781352f7f91STakashi Iwai 	static const char * const texts3[] = {
2782352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
27831da177e4SLinus Torvalds 	};
27841da177e4SLinus Torvalds 
2785352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
2786352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
2787352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
2788352f7f91STakashi Iwai }
2789352f7f91STakashi Iwai 
2790352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
2791352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2792352f7f91STakashi Iwai {
2793352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2794352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2795352f7f91STakashi Iwai 	unsigned int val = 0;
2796352f7f91STakashi Iwai 	if (spec->automute_speaker)
2797352f7f91STakashi Iwai 		val++;
2798352f7f91STakashi Iwai 	if (spec->automute_lo)
2799352f7f91STakashi Iwai 		val++;
2800352f7f91STakashi Iwai 
2801352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
2802352f7f91STakashi Iwai 	return 0;
2803352f7f91STakashi Iwai }
2804352f7f91STakashi Iwai 
2805352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
2806352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2807352f7f91STakashi Iwai {
2808352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2809352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2810352f7f91STakashi Iwai 
2811352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
2812352f7f91STakashi Iwai 	case 0:
2813352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
2814352f7f91STakashi Iwai 			return 0;
2815352f7f91STakashi Iwai 		spec->automute_speaker = 0;
2816352f7f91STakashi Iwai 		spec->automute_lo = 0;
2817352f7f91STakashi Iwai 		break;
2818352f7f91STakashi Iwai 	case 1:
2819352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
2820352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
2821352f7f91STakashi Iwai 				return 0;
2822352f7f91STakashi Iwai 			spec->automute_speaker = 1;
2823352f7f91STakashi Iwai 			spec->automute_lo = 0;
2824352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
2825352f7f91STakashi Iwai 			if (spec->automute_lo)
2826352f7f91STakashi Iwai 				return 0;
2827352f7f91STakashi Iwai 			spec->automute_lo = 1;
2828352f7f91STakashi Iwai 		} else
2829352f7f91STakashi Iwai 			return -EINVAL;
2830352f7f91STakashi Iwai 		break;
2831352f7f91STakashi Iwai 	case 2:
2832352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
2833352f7f91STakashi Iwai 			return -EINVAL;
2834352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
2835352f7f91STakashi Iwai 			return 0;
2836352f7f91STakashi Iwai 		spec->automute_speaker = 1;
2837352f7f91STakashi Iwai 		spec->automute_lo = 1;
2838352f7f91STakashi Iwai 		break;
2839352f7f91STakashi Iwai 	default:
2840352f7f91STakashi Iwai 		return -EINVAL;
2841352f7f91STakashi Iwai 	}
2842352f7f91STakashi Iwai 	call_update_outputs(codec);
2843352f7f91STakashi Iwai 	return 1;
2844352f7f91STakashi Iwai }
2845352f7f91STakashi Iwai 
2846352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
2847352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2848352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
2849352f7f91STakashi Iwai 	.info = automute_mode_info,
2850352f7f91STakashi Iwai 	.get = automute_mode_get,
2851352f7f91STakashi Iwai 	.put = automute_mode_put,
2852352f7f91STakashi Iwai };
2853352f7f91STakashi Iwai 
2854352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
2855352f7f91STakashi Iwai {
2856352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2857352f7f91STakashi Iwai 
285812c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
2859352f7f91STakashi Iwai 		return -ENOMEM;
2860352f7f91STakashi Iwai 	return 0;
2861352f7f91STakashi Iwai }
2862352f7f91STakashi Iwai 
2863352f7f91STakashi Iwai /*
2864352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
2865352f7f91STakashi Iwai  * Set up appropriately if really supported
2866352f7f91STakashi Iwai  */
2867352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
2868352f7f91STakashi Iwai {
2869352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2870352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2871352f7f91STakashi Iwai 	int present = 0;
2872352f7f91STakashi Iwai 	int i, err;
2873352f7f91STakashi Iwai 
2874352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
2875352f7f91STakashi Iwai 		present++;
2876352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
2877352f7f91STakashi Iwai 		present++;
2878352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
2879352f7f91STakashi Iwai 		present++;
2880352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
2881352f7f91STakashi Iwai 		return 0;
2882352f7f91STakashi Iwai 
2883352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
2884352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2885352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2886352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2887352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2888352f7f91STakashi Iwai 	}
2889352f7f91STakashi Iwai 
2890352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
2891352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2892352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
2893352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
2894352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
2895352f7f91STakashi Iwai 	}
2896352f7f91STakashi Iwai 
2897352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
2898352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
2899352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
2900352f7f91STakashi Iwai 			continue;
2901352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
2902352f7f91STakashi Iwai 			    nid);
2903352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
29042e03e952STakashi Iwai 						    spec->hp_automute_hook ?
29052e03e952STakashi Iwai 						    spec->hp_automute_hook :
29065d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
2907352f7f91STakashi Iwai 		spec->detect_hp = 1;
2908352f7f91STakashi Iwai 	}
2909352f7f91STakashi Iwai 
2910352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
2911352f7f91STakashi Iwai 		if (cfg->speaker_outs)
2912352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
2913352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
2914352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
2915352f7f91STakashi Iwai 					continue;
2916352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
2917352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
2918352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
29192e03e952STakashi Iwai 								    spec->line_automute_hook ?
29202e03e952STakashi Iwai 								    spec->line_automute_hook :
29215d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
2922352f7f91STakashi Iwai 				spec->detect_lo = 1;
2923352f7f91STakashi Iwai 			}
2924352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
2925352f7f91STakashi Iwai 	}
2926352f7f91STakashi Iwai 
2927352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
2928352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
2929352f7f91STakashi Iwai 
2930352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
2931352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
2932352f7f91STakashi Iwai 
2933352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
2934352f7f91STakashi Iwai 		/* create a control for automute mode */
2935352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
2936352f7f91STakashi Iwai 		if (err < 0)
2937352f7f91STakashi Iwai 			return err;
2938352f7f91STakashi Iwai 	}
2939352f7f91STakashi Iwai 	return 0;
2940352f7f91STakashi Iwai }
2941352f7f91STakashi Iwai 
2942352f7f91STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2943352f7f91STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2944352f7f91STakashi Iwai {
2945352f7f91STakashi Iwai 	int i;
2946352f7f91STakashi Iwai 	for (i = 0; i < nums; i++)
2947352f7f91STakashi Iwai 		if (list[i] == nid)
2948352f7f91STakashi Iwai 			return i;
2949352f7f91STakashi Iwai 	return -1;
2950352f7f91STakashi Iwai }
2951352f7f91STakashi Iwai 
2952352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
2953352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
2954352f7f91STakashi Iwai {
2955352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2956352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2957352f7f91STakashi Iwai 	int i;
2958352f7f91STakashi Iwai 
2959352f7f91STakashi Iwai 	imux = &spec->input_mux;
2960352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
2961352f7f91STakashi Iwai 		spec->am_entry[i].idx =
2962352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
2963352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
2964352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
2965352f7f91STakashi Iwai 			return false; /* no corresponding imux */
2966352f7f91STakashi Iwai 	}
2967352f7f91STakashi Iwai 
2968352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
2969352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
2970352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
2971352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
2972352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
29732e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
29742e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
29755d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
2976352f7f91STakashi Iwai 	return true;
2977352f7f91STakashi Iwai }
2978352f7f91STakashi Iwai 
2979352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
2980352f7f91STakashi Iwai {
2981352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
2982352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
2983352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
2984352f7f91STakashi Iwai }
2985352f7f91STakashi Iwai 
2986352f7f91STakashi Iwai /*
2987352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
2988352f7f91STakashi Iwai  * Set up if really supported
2989352f7f91STakashi Iwai  */
2990352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
2991352f7f91STakashi Iwai {
2992352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2993352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2994352f7f91STakashi Iwai 	unsigned int types;
2995352f7f91STakashi Iwai 	int i, num_pins;
2996352f7f91STakashi Iwai 
2997352f7f91STakashi Iwai 	types = 0;
2998352f7f91STakashi Iwai 	num_pins = 0;
2999352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3000352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3001352f7f91STakashi Iwai 		unsigned int attr;
3002352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3003352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3004352f7f91STakashi Iwai 		if (types & (1 << attr))
3005352f7f91STakashi Iwai 			return 0; /* already occupied */
3006352f7f91STakashi Iwai 		switch (attr) {
3007352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3008352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3009352f7f91STakashi Iwai 				return 0; /* invalid type */
3010352f7f91STakashi Iwai 			break;
3011352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3012352f7f91STakashi Iwai 			return 0; /* invalid entry */
3013352f7f91STakashi Iwai 		default:
3014352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3015352f7f91STakashi Iwai 				return 0; /* invalid type */
3016352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3017352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3018352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3019352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3020352f7f91STakashi Iwai 				return 0; /* no unsol support */
3021352f7f91STakashi Iwai 			break;
3022352f7f91STakashi Iwai 		}
3023352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3024352f7f91STakashi Iwai 			return 0;
3025352f7f91STakashi Iwai 		types |= (1 << attr);
3026352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3027352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3028352f7f91STakashi Iwai 		num_pins++;
3029352f7f91STakashi Iwai 	}
3030352f7f91STakashi Iwai 
3031352f7f91STakashi Iwai 	if (num_pins < 2)
3032352f7f91STakashi Iwai 		return 0;
3033352f7f91STakashi Iwai 
3034352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3035352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3036352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3037352f7f91STakashi Iwai 	 */
3038352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3039352f7f91STakashi Iwai 	     compare_attr, NULL);
3040352f7f91STakashi Iwai 
3041352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3042352f7f91STakashi Iwai 		return 0;
3043352f7f91STakashi Iwai 
3044352f7f91STakashi Iwai 	spec->auto_mic = 1;
3045352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3046352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3047352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3048352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3049352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3050352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3051352f7f91STakashi Iwai 
3052352f7f91STakashi Iwai 	return 0;
3053352f7f91STakashi Iwai }
3054352f7f91STakashi Iwai 
3055352f7f91STakashi Iwai 
30569eb413e5STakashi Iwai /*
30579eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
30589eb413e5STakashi Iwai  *
30599eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3060352f7f91STakashi Iwai  * or a negative error code
3061352f7f91STakashi Iwai  */
3062352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
30639eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3064352f7f91STakashi Iwai {
3065352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3066352f7f91STakashi Iwai 	int err;
3067352f7f91STakashi Iwai 
30689eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
30699eb413e5STakashi Iwai 		spec->autocfg = *cfg;
30709eb413e5STakashi Iwai 		cfg = &spec->autocfg;
30719eb413e5STakashi Iwai 	}
30729eb413e5STakashi Iwai 
3073352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3074352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3075352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3076352f7f91STakashi Iwai 			spec->no_analog = 1;
3077352f7f91STakashi Iwai 			goto dig_only;
3078352f7f91STakashi Iwai 		}
3079352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3080352f7f91STakashi Iwai 	}
3081352f7f91STakashi Iwai 
3082352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3083352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3084352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3085352f7f91STakashi Iwai 		/* use HP as primary out */
3086352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3087352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3088352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3089352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3090352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3091352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3092352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3093352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3094352f7f91STakashi Iwai 	}
3095352f7f91STakashi Iwai 
3096352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3097352f7f91STakashi Iwai 	if (err < 0)
3098352f7f91STakashi Iwai 		return err;
3099352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3100352f7f91STakashi Iwai 	if (err < 0)
3101352f7f91STakashi Iwai 		return err;
3102352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3103352f7f91STakashi Iwai 	if (err < 0)
3104352f7f91STakashi Iwai 		return err;
3105352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3106352f7f91STakashi Iwai 	if (err < 0)
3107352f7f91STakashi Iwai 		return err;
3108352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3109352f7f91STakashi Iwai 	if (err < 0)
3110352f7f91STakashi Iwai 		return err;
311138cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
311238cf6f1aSTakashi Iwai 	if (err < 0)
311338cf6f1aSTakashi Iwai 		return err;
3114c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3115c30aa7b2STakashi Iwai 	if (err < 0)
3116c30aa7b2STakashi Iwai 		return err;
3117352f7f91STakashi Iwai 	err = create_shared_input(codec);
3118352f7f91STakashi Iwai 	if (err < 0)
3119352f7f91STakashi Iwai 		return err;
3120352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3121352f7f91STakashi Iwai 	if (err < 0)
3122352f7f91STakashi Iwai 		return err;
3123352f7f91STakashi Iwai 
3124352f7f91STakashi Iwai 	/* check the multiple speaker pins */
3125352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
3126352f7f91STakashi Iwai 		spec->const_channel_count = cfg->line_outs * 2;
3127352f7f91STakashi Iwai 	else
3128352f7f91STakashi Iwai 		spec->const_channel_count = cfg->speaker_outs * 2;
3129352f7f91STakashi Iwai 
3130352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
3131352f7f91STakashi Iwai 		spec->multiout.max_channels = max(spec->ext_channel_count,
3132352f7f91STakashi Iwai 						  spec->const_channel_count);
3133352f7f91STakashi Iwai 	else
3134352f7f91STakashi Iwai 		spec->multiout.max_channels = spec->multiout.num_dacs * 2;
3135352f7f91STakashi Iwai 
3136352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3137352f7f91STakashi Iwai 	if (err < 0)
3138352f7f91STakashi Iwai 		return err;
3139352f7f91STakashi Iwai 
3140352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3141352f7f91STakashi Iwai 	if (err < 0)
3142352f7f91STakashi Iwai 		return err;
3143352f7f91STakashi Iwai 
3144352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3145352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3146352f7f91STakashi Iwai 		if (err < 0)
3147352f7f91STakashi Iwai 			return err;
3148352f7f91STakashi Iwai 	}
3149352f7f91STakashi Iwai 
3150352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3151352f7f91STakashi Iwai 	if (err < 0)
3152352f7f91STakashi Iwai 		return err;
3153352f7f91STakashi Iwai 
3154352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3155352f7f91STakashi Iwai 	if (err < 0)
3156352f7f91STakashi Iwai 		return err;
3157352f7f91STakashi Iwai 
3158352f7f91STakashi Iwai  dig_only:
3159352f7f91STakashi Iwai 	parse_digital(codec);
3160352f7f91STakashi Iwai 
3161352f7f91STakashi Iwai 	return 1;
3162352f7f91STakashi Iwai }
3163352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3164352f7f91STakashi Iwai 
3165352f7f91STakashi Iwai 
3166352f7f91STakashi Iwai /*
3167352f7f91STakashi Iwai  * Build control elements
3168352f7f91STakashi Iwai  */
3169352f7f91STakashi Iwai 
3170352f7f91STakashi Iwai /* slave controls for virtual master */
3171352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3172352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3173352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3174352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3175ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3176ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3177ee79c69aSTakashi Iwai 	"Headphone Side",
3178352f7f91STakashi Iwai 	NULL,
3179352f7f91STakashi Iwai };
3180352f7f91STakashi Iwai 
3181352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3182352f7f91STakashi Iwai {
3183352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3184352f7f91STakashi Iwai 	int err;
3185352f7f91STakashi Iwai 
318636502d02STakashi Iwai 	if (spec->kctls.used) {
3187352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3188352f7f91STakashi Iwai 		if (err < 0)
3189352f7f91STakashi Iwai 			return err;
319036502d02STakashi Iwai 	}
3191352f7f91STakashi Iwai 
3192352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3193352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3194352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3195352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3196352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3197352f7f91STakashi Iwai 		if (err < 0)
3198352f7f91STakashi Iwai 			return err;
3199352f7f91STakashi Iwai 		if (!spec->no_analog) {
3200352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3201352f7f91STakashi Iwai 							    &spec->multiout);
3202352f7f91STakashi Iwai 			if (err < 0)
3203352f7f91STakashi Iwai 				return err;
3204352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3205352f7f91STakashi Iwai 		}
3206352f7f91STakashi Iwai 	}
3207352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3208352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3209352f7f91STakashi Iwai 		if (err < 0)
3210352f7f91STakashi Iwai 			return err;
3211352f7f91STakashi Iwai 	}
3212352f7f91STakashi Iwai 
3213352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3214352f7f91STakashi Iwai 	if (!spec->no_analog &&
3215352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3216352f7f91STakashi Iwai 		unsigned int vmaster_tlv[4];
3217352f7f91STakashi Iwai 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
3218352f7f91STakashi Iwai 					HDA_OUTPUT, vmaster_tlv);
3219352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
3220352f7f91STakashi Iwai 					  vmaster_tlv, slave_pfxs,
3221352f7f91STakashi Iwai 					  "Playback Volume");
3222352f7f91STakashi Iwai 		if (err < 0)
3223352f7f91STakashi Iwai 			return err;
3224352f7f91STakashi Iwai 	}
3225352f7f91STakashi Iwai 	if (!spec->no_analog &&
3226352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3227352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3228352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3229352f7f91STakashi Iwai 					    "Playback Switch",
3230352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3231352f7f91STakashi Iwai 		if (err < 0)
3232352f7f91STakashi Iwai 			return err;
3233352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3234fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3235fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3236352f7f91STakashi Iwai 	}
3237352f7f91STakashi Iwai 
3238352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3239352f7f91STakashi Iwai 
3240352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3241352f7f91STakashi Iwai 		int err;
3242352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3243352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3244352f7f91STakashi Iwai 		if (err < 0)
3245352f7f91STakashi Iwai 			return err;
3246352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3247352f7f91STakashi Iwai 		if (err < 0)
3248352f7f91STakashi Iwai 			return err;
3249352f7f91STakashi Iwai 	}
3250352f7f91STakashi Iwai 
3251352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3252352f7f91STakashi Iwai 	if (err < 0)
3253352f7f91STakashi Iwai 		return err;
3254352f7f91STakashi Iwai 
3255352f7f91STakashi Iwai 	return 0;
3256352f7f91STakashi Iwai }
3257352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3258352f7f91STakashi Iwai 
3259352f7f91STakashi Iwai 
3260352f7f91STakashi Iwai /*
3261352f7f91STakashi Iwai  * PCM definitions
3262352f7f91STakashi Iwai  */
3263352f7f91STakashi Iwai 
3264e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
3265e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
3266e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
3267e6b85f3cSTakashi Iwai 				   int action)
3268e6b85f3cSTakashi Iwai {
3269e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3270e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
3271e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
3272e6b85f3cSTakashi Iwai }
3273e6b85f3cSTakashi Iwai 
3274352f7f91STakashi Iwai /*
3275352f7f91STakashi Iwai  * Analog playback callbacks
3276352f7f91STakashi Iwai  */
3277352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3278352f7f91STakashi Iwai 			     struct hda_codec *codec,
3279352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3280352f7f91STakashi Iwai {
3281352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
328238cf6f1aSTakashi Iwai 	int err;
328338cf6f1aSTakashi Iwai 
328438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
328538cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
328638cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3287352f7f91STakashi Iwai 					     hinfo);
3288e6b85f3cSTakashi Iwai 	if (!err) {
328938cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
3290e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3291e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
3292e6b85f3cSTakashi Iwai 	}
329338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
329438cf6f1aSTakashi Iwai 	return err;
3295352f7f91STakashi Iwai }
3296352f7f91STakashi Iwai 
3297352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
329897ec558aSTakashi Iwai 				struct hda_codec *codec,
329997ec558aSTakashi Iwai 				unsigned int stream_tag,
330097ec558aSTakashi Iwai 				unsigned int format,
330197ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
330297ec558aSTakashi Iwai {
3303352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3304e6b85f3cSTakashi Iwai 	int err;
3305e6b85f3cSTakashi Iwai 
3306e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3307352f7f91STakashi Iwai 					       stream_tag, format, substream);
3308e6b85f3cSTakashi Iwai 	if (!err)
3309e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3310e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
3311e6b85f3cSTakashi Iwai 	return err;
3312352f7f91STakashi Iwai }
331397ec558aSTakashi Iwai 
3314352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3315352f7f91STakashi Iwai 				struct hda_codec *codec,
3316352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3317352f7f91STakashi Iwai {
3318352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3319e6b85f3cSTakashi Iwai 	int err;
3320e6b85f3cSTakashi Iwai 
3321e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3322e6b85f3cSTakashi Iwai 	if (!err)
3323e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3324e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
3325e6b85f3cSTakashi Iwai 	return err;
3326352f7f91STakashi Iwai }
3327352f7f91STakashi Iwai 
332838cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
332938cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
333038cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
333138cf6f1aSTakashi Iwai {
333238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
333338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
333438cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
3335e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3336e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
333738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
333838cf6f1aSTakashi Iwai 	return 0;
333938cf6f1aSTakashi Iwai }
334038cf6f1aSTakashi Iwai 
334138cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
334238cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
334338cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
334438cf6f1aSTakashi Iwai {
334538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
334638cf6f1aSTakashi Iwai 	int err = 0;
334738cf6f1aSTakashi Iwai 
334838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
334938cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
335038cf6f1aSTakashi Iwai 		err = -EBUSY;
335138cf6f1aSTakashi Iwai 	else
335238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
3353e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3354e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
335538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
335638cf6f1aSTakashi Iwai 	return err;
335738cf6f1aSTakashi Iwai }
335838cf6f1aSTakashi Iwai 
335938cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
336038cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
336138cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
336238cf6f1aSTakashi Iwai {
336338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
336438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
336538cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
3366e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3367e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
336838cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
336938cf6f1aSTakashi Iwai 	return 0;
337038cf6f1aSTakashi Iwai }
337138cf6f1aSTakashi Iwai 
3372e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3373e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
3374e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
3375e6b85f3cSTakashi Iwai 				    unsigned int format,
3376e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
3377e6b85f3cSTakashi Iwai {
3378e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3379e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3380e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
3381e6b85f3cSTakashi Iwai 	return 0;
3382e6b85f3cSTakashi Iwai }
3383e6b85f3cSTakashi Iwai 
3384e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3385e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
3386e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
3387e6b85f3cSTakashi Iwai {
3388e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
3389e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3390e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
3391e6b85f3cSTakashi Iwai 	return 0;
3392e6b85f3cSTakashi Iwai }
3393e6b85f3cSTakashi Iwai 
3394352f7f91STakashi Iwai /*
3395352f7f91STakashi Iwai  * Digital out
3396352f7f91STakashi Iwai  */
3397352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3398352f7f91STakashi Iwai 				 struct hda_codec *codec,
3399352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
3400352f7f91STakashi Iwai {
3401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3402352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3403352f7f91STakashi Iwai }
3404352f7f91STakashi Iwai 
3405352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3406352f7f91STakashi Iwai 				    struct hda_codec *codec,
3407352f7f91STakashi Iwai 				    unsigned int stream_tag,
3408352f7f91STakashi Iwai 				    unsigned int format,
3409352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3410352f7f91STakashi Iwai {
3411352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3412352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3413352f7f91STakashi Iwai 					     stream_tag, format, substream);
3414352f7f91STakashi Iwai }
3415352f7f91STakashi Iwai 
3416352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3417352f7f91STakashi Iwai 				    struct hda_codec *codec,
3418352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3419352f7f91STakashi Iwai {
3420352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3421352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3422352f7f91STakashi Iwai }
3423352f7f91STakashi Iwai 
3424352f7f91STakashi Iwai static int dig_playback_pcm_close(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_close(codec, &spec->multiout);
3430352f7f91STakashi Iwai }
3431352f7f91STakashi Iwai 
3432352f7f91STakashi Iwai /*
3433352f7f91STakashi Iwai  * Analog capture
3434352f7f91STakashi Iwai  */
3435352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3436352f7f91STakashi Iwai 				   struct hda_codec *codec,
3437352f7f91STakashi Iwai 				   unsigned int stream_tag,
3438352f7f91STakashi Iwai 				   unsigned int format,
3439352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
3440352f7f91STakashi Iwai {
3441352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3442352f7f91STakashi Iwai 
3443352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
344497ec558aSTakashi Iwai 				   stream_tag, 0, format);
344597ec558aSTakashi Iwai 	return 0;
344697ec558aSTakashi Iwai }
344797ec558aSTakashi Iwai 
3448352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
344997ec558aSTakashi Iwai 				   struct hda_codec *codec,
345097ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
345197ec558aSTakashi Iwai {
3452352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
345397ec558aSTakashi Iwai 
3454352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
3455352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
345697ec558aSTakashi Iwai 	return 0;
345797ec558aSTakashi Iwai }
345897ec558aSTakashi Iwai 
3459352f7f91STakashi Iwai /*
3460352f7f91STakashi Iwai  */
3461352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
3462352f7f91STakashi Iwai 	.substreams = 1,
3463352f7f91STakashi Iwai 	.channels_min = 2,
3464352f7f91STakashi Iwai 	.channels_max = 8,
3465352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3466352f7f91STakashi Iwai 	.ops = {
3467352f7f91STakashi Iwai 		.open = playback_pcm_open,
346838cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
3469352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
3470352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
3471352f7f91STakashi Iwai 	},
3472352f7f91STakashi Iwai };
3473352f7f91STakashi Iwai 
3474352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
3475352f7f91STakashi Iwai 	.substreams = 1,
3476352f7f91STakashi Iwai 	.channels_min = 2,
3477352f7f91STakashi Iwai 	.channels_max = 2,
3478352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3479352f7f91STakashi Iwai };
3480352f7f91STakashi Iwai 
3481352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
3482352f7f91STakashi Iwai 	.substreams = 1,
3483352f7f91STakashi Iwai 	.channels_min = 2,
3484352f7f91STakashi Iwai 	.channels_max = 2,
3485352f7f91STakashi Iwai 	/* NID is set in build_pcms */
348638cf6f1aSTakashi Iwai 	.ops = {
348738cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
3488e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
3489e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
3490e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
349138cf6f1aSTakashi Iwai 	},
3492352f7f91STakashi Iwai };
3493352f7f91STakashi Iwai 
3494352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
3495352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
3496352f7f91STakashi Iwai 	.channels_min = 2,
3497352f7f91STakashi Iwai 	.channels_max = 2,
3498352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3499352f7f91STakashi Iwai 	.ops = {
3500352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
3501352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
3502352f7f91STakashi Iwai 	},
3503352f7f91STakashi Iwai };
3504352f7f91STakashi Iwai 
3505352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
3506352f7f91STakashi Iwai 	.substreams = 1,
3507352f7f91STakashi Iwai 	.channels_min = 2,
3508352f7f91STakashi Iwai 	.channels_max = 2,
3509352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3510352f7f91STakashi Iwai 	.ops = {
3511352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
3512352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
3513352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
3514352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
3515352f7f91STakashi Iwai 	},
3516352f7f91STakashi Iwai };
3517352f7f91STakashi Iwai 
3518352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
3519352f7f91STakashi Iwai 	.substreams = 1,
3520352f7f91STakashi Iwai 	.channels_min = 2,
3521352f7f91STakashi Iwai 	.channels_max = 2,
3522352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3523352f7f91STakashi Iwai };
3524352f7f91STakashi Iwai 
3525352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
3526352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
3527352f7f91STakashi Iwai 	.substreams = 0,
3528352f7f91STakashi Iwai 	.channels_min = 0,
3529352f7f91STakashi Iwai 	.channels_max = 0,
3530352f7f91STakashi Iwai };
3531352f7f91STakashi Iwai 
3532352f7f91STakashi Iwai /*
3533352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
3534352f7f91STakashi Iwai  */
3535352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
35361da177e4SLinus Torvalds {
3537352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3538352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
35391da177e4SLinus Torvalds 
3540352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
3541352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
3542352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3543352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
3544352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
3545352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
3546352f7f91STakashi Iwai 					   spec->cur_adc_format);
3547352f7f91STakashi Iwai 		return true;
3548352f7f91STakashi Iwai 	}
3549352f7f91STakashi Iwai 	return false;
3550352f7f91STakashi Iwai }
3551352f7f91STakashi Iwai 
3552352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
3553352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3554352f7f91STakashi Iwai 				       struct hda_codec *codec,
3555352f7f91STakashi Iwai 				       unsigned int stream_tag,
3556352f7f91STakashi Iwai 				       unsigned int format,
3557352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3558352f7f91STakashi Iwai {
3559352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3560352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
3561352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
3562352f7f91STakashi Iwai 	spec->cur_adc_format = format;
3563352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
35641da177e4SLinus Torvalds 	return 0;
35651da177e4SLinus Torvalds }
35661da177e4SLinus Torvalds 
3567352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3568352f7f91STakashi Iwai 				       struct hda_codec *codec,
3569352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3570352f7f91STakashi Iwai {
3571352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3572352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3573352f7f91STakashi Iwai 	spec->cur_adc = 0;
3574352f7f91STakashi Iwai 	return 0;
3575352f7f91STakashi Iwai }
3576352f7f91STakashi Iwai 
3577352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
3578352f7f91STakashi Iwai 	.substreams = 1,
3579352f7f91STakashi Iwai 	.channels_min = 2,
3580352f7f91STakashi Iwai 	.channels_max = 2,
3581352f7f91STakashi Iwai 	.nid = 0, /* fill later */
3582352f7f91STakashi Iwai 	.ops = {
3583352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
3584352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
3585352f7f91STakashi Iwai 	},
3586352f7f91STakashi Iwai };
3587352f7f91STakashi Iwai 
3588f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
3589f873e536STakashi Iwai 				 const char *chip_name)
3590f873e536STakashi Iwai {
3591f873e536STakashi Iwai 	char *p;
3592f873e536STakashi Iwai 
3593f873e536STakashi Iwai 	if (*str)
3594f873e536STakashi Iwai 		return;
3595f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
3596f873e536STakashi Iwai 
3597f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
3598f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
3599f873e536STakashi Iwai 		if (!isalnum(p[1])) {
3600f873e536STakashi Iwai 			*p = 0;
3601f873e536STakashi Iwai 			break;
3602f873e536STakashi Iwai 		}
3603f873e536STakashi Iwai 	}
3604f873e536STakashi Iwai 	strlcat(str, sfx, len);
3605f873e536STakashi Iwai }
3606f873e536STakashi Iwai 
3607352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
3608352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
3609352f7f91STakashi Iwai {
3610352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3611352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
3612352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
3613352f7f91STakashi Iwai 	bool have_multi_adcs;
3614352f7f91STakashi Iwai 
36151da177e4SLinus Torvalds 	codec->num_pcms = 1;
36161da177e4SLinus Torvalds 	codec->pcm_info = info;
36171da177e4SLinus Torvalds 
3618352f7f91STakashi Iwai 	if (spec->no_analog)
3619352f7f91STakashi Iwai 		goto skip_analog;
3620352f7f91STakashi Iwai 
3621f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
3622f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
3623f873e536STakashi Iwai 			     " Analog", codec->chip_name);
3624352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
3625352f7f91STakashi Iwai 
3626352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
3627352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
3628352f7f91STakashi Iwai 		if (!p)
3629352f7f91STakashi Iwai 			p = &pcm_analog_playback;
3630352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3631352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3632352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3633352f7f91STakashi Iwai 			spec->multiout.max_channels;
3634352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
3635352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
3636352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
3637352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
3638352f7f91STakashi Iwai 	}
3639352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
3640352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
3641352f7f91STakashi Iwai 		if (!p) {
3642352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
3643352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
3644352f7f91STakashi Iwai 			else
3645352f7f91STakashi Iwai 				p = &pcm_analog_capture;
3646352f7f91STakashi Iwai 		}
3647352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3648352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3649352f7f91STakashi Iwai 	}
3650352f7f91STakashi Iwai 
3651352f7f91STakashi Iwai  skip_analog:
3652352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
3653352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3654f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
3655352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
3656f873e536STakashi Iwai 				     " Digital", codec->chip_name);
3657352f7f91STakashi Iwai 		codec->num_pcms = 2;
3658352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
3659352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
3660352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
3661352f7f91STakashi Iwai 		if (spec->dig_out_type)
3662352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
3663352f7f91STakashi Iwai 		else
3664352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
3665352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
3666352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
3667352f7f91STakashi Iwai 			if (!p)
3668352f7f91STakashi Iwai 				p = &pcm_digital_playback;
3669352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3670352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3671352f7f91STakashi Iwai 		}
3672352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
3673352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
3674352f7f91STakashi Iwai 			if (!p)
3675352f7f91STakashi Iwai 				p = &pcm_digital_capture;
3676352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3677352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3678352f7f91STakashi Iwai 		}
3679352f7f91STakashi Iwai 	}
3680352f7f91STakashi Iwai 
3681352f7f91STakashi Iwai 	if (spec->no_analog)
3682352f7f91STakashi Iwai 		return 0;
3683352f7f91STakashi Iwai 
3684352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
3685352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
3686352f7f91STakashi Iwai 	 */
3687352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
3688352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
3689352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
3690352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
3691352f7f91STakashi Iwai 		codec->num_pcms = 3;
3692352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
3693352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
3694352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
3695352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
3696352f7f91STakashi Iwai 			if (!p)
3697352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
3698352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3699352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3700352f7f91STakashi Iwai 				spec->alt_dac_nid;
3701352f7f91STakashi Iwai 		} else {
3702352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3703352f7f91STakashi Iwai 				pcm_null_stream;
3704352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3705352f7f91STakashi Iwai 		}
3706352f7f91STakashi Iwai 		if (have_multi_adcs) {
3707352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
3708352f7f91STakashi Iwai 			if (!p)
3709352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
3710352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3711352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3712352f7f91STakashi Iwai 				spec->adc_nids[1];
3713352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3714352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
3715352f7f91STakashi Iwai 		} else {
3716352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3717352f7f91STakashi Iwai 				pcm_null_stream;
3718352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
3719352f7f91STakashi Iwai 		}
37201da177e4SLinus Torvalds 	}
37211da177e4SLinus Torvalds 
37221da177e4SLinus Torvalds 	return 0;
37231da177e4SLinus Torvalds }
3724352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
3725352f7f91STakashi Iwai 
3726352f7f91STakashi Iwai 
3727352f7f91STakashi Iwai /*
3728352f7f91STakashi Iwai  * Standard auto-parser initializations
3729352f7f91STakashi Iwai  */
3730352f7f91STakashi Iwai 
3731d4156930STakashi Iwai /* configure the given path as a proper output */
3732d4156930STakashi Iwai static void set_output_and_unmute(struct hda_codec *codec,
3733196c1766STakashi Iwai 				  int pin_type, int path_idx)
3734352f7f91STakashi Iwai {
3735352f7f91STakashi Iwai 	struct nid_path *path;
3736d4156930STakashi Iwai 	hda_nid_t pin;
3737352f7f91STakashi Iwai 
3738196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
3739d4156930STakashi Iwai 	if (!path || !path->depth)
3740352f7f91STakashi Iwai 		return;
3741d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
3742d4156930STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, pin_type);
3743e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
3744e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
3745352f7f91STakashi Iwai }
3746352f7f91STakashi Iwai 
3747352f7f91STakashi Iwai /* initialize primary output paths */
3748352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
3749352f7f91STakashi Iwai {
3750352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3751352f7f91STakashi Iwai 	int pin_type;
3752352f7f91STakashi Iwai 	int i;
3753352f7f91STakashi Iwai 
3754352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3755352f7f91STakashi Iwai 		pin_type = PIN_HP;
3756352f7f91STakashi Iwai 	else
3757352f7f91STakashi Iwai 		pin_type = PIN_OUT;
3758352f7f91STakashi Iwai 
3759d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
3760d4156930STakashi Iwai 		set_output_and_unmute(codec, pin_type, spec->out_paths[i]);
3761352f7f91STakashi Iwai }
3762352f7f91STakashi Iwai 
3763db23fd19STakashi Iwai 
3764db23fd19STakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs,
3765d4156930STakashi Iwai 			     int *paths, int type)
3766352f7f91STakashi Iwai {
3767352f7f91STakashi Iwai 	int i;
3768352f7f91STakashi Iwai 
3769d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
3770d4156930STakashi Iwai 		set_output_and_unmute(codec, type, paths[i]);
3771352f7f91STakashi Iwai }
3772db23fd19STakashi Iwai 
3773db23fd19STakashi Iwai /* initialize hp and speaker paths */
3774db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
3775db23fd19STakashi Iwai {
3776db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3777db23fd19STakashi Iwai 
3778db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
3779db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs,
3780196c1766STakashi Iwai 				 spec->hp_paths, PIN_HP);
3781db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
3782db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
3783196c1766STakashi Iwai 				 spec->speaker_paths, PIN_OUT);
3784352f7f91STakashi Iwai }
3785352f7f91STakashi Iwai 
3786352f7f91STakashi Iwai /* initialize multi-io paths */
3787352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
3788352f7f91STakashi Iwai {
3789352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3790352f7f91STakashi Iwai 	int i;
3791352f7f91STakashi Iwai 
3792352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
3793352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
3794352f7f91STakashi Iwai 		struct nid_path *path;
3795196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
3796352f7f91STakashi Iwai 		if (!path)
3797352f7f91STakashi Iwai 			continue;
3798352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
3799352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
3800352f7f91STakashi Iwai 				snd_hda_codec_update_cache(codec, pin, 0,
3801352f7f91STakashi Iwai 					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3802352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
3803352f7f91STakashi Iwai 	}
3804352f7f91STakashi Iwai }
3805352f7f91STakashi Iwai 
3806352f7f91STakashi Iwai /* set up the input pin config, depending on the given auto-pin type */
3807352f7f91STakashi Iwai static void set_input_pin(struct hda_codec *codec, hda_nid_t nid,
3808352f7f91STakashi Iwai 			  int auto_pin_type)
3809352f7f91STakashi Iwai {
3810352f7f91STakashi Iwai 	unsigned int val = PIN_IN;
3811352f7f91STakashi Iwai 	if (auto_pin_type == AUTO_PIN_MIC)
3812352f7f91STakashi Iwai 		val |= snd_hda_get_default_vref(codec, nid);
38137594aa33STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
3814352f7f91STakashi Iwai }
3815352f7f91STakashi Iwai 
3816352f7f91STakashi Iwai /* set up input pins and loopback paths */
3817352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
3818352f7f91STakashi Iwai {
3819352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3820352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3821352f7f91STakashi Iwai 	int i;
3822352f7f91STakashi Iwai 
3823352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3824352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3825352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
3826352f7f91STakashi Iwai 			set_input_pin(codec, nid, cfg->inputs[i].type);
3827352f7f91STakashi Iwai 
3828352f7f91STakashi Iwai 		/* init loopback inputs */
3829352f7f91STakashi Iwai 		if (spec->mixer_nid) {
3830352f7f91STakashi Iwai 			struct nid_path *path;
3831196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
3832352f7f91STakashi Iwai 			if (path)
3833352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
3834352f7f91STakashi Iwai 						      path->active, false);
3835352f7f91STakashi Iwai 		}
3836352f7f91STakashi Iwai 	}
3837352f7f91STakashi Iwai }
3838352f7f91STakashi Iwai 
3839352f7f91STakashi Iwai /* initialize ADC paths */
3840352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
3841352f7f91STakashi Iwai {
3842352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3843352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3844352f7f91STakashi Iwai 	struct nid_path *path;
3845352f7f91STakashi Iwai 	int i, c, nums;
3846352f7f91STakashi Iwai 
3847352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3848352f7f91STakashi Iwai 		nums = 1;
3849352f7f91STakashi Iwai 	else
3850352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3851352f7f91STakashi Iwai 
3852352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
3853352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3854352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
3855352f7f91STakashi Iwai 						    get_adc_nid(codec, c, i));
3856352f7f91STakashi Iwai 			if (path) {
3857352f7f91STakashi Iwai 				bool active = path->active;
3858352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
3859352f7f91STakashi Iwai 					active = true;
3860352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
3861352f7f91STakashi Iwai 			}
3862352f7f91STakashi Iwai 		}
3863352f7f91STakashi Iwai 	}
3864352f7f91STakashi Iwai 
3865352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3866352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
3867352f7f91STakashi Iwai 
3868352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3869352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
3870352f7f91STakashi Iwai }
3871352f7f91STakashi Iwai 
3872352f7f91STakashi Iwai /* set right pin controls for digital I/O */
3873352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
3874352f7f91STakashi Iwai {
3875352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3876352f7f91STakashi Iwai 	int i;
3877352f7f91STakashi Iwai 	hda_nid_t pin;
3878352f7f91STakashi Iwai 
3879d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
3880d4156930STakashi Iwai 		set_output_and_unmute(codec, PIN_OUT, spec->digout_paths[i]);
3881352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
38822430d7b7STakashi Iwai 	if (pin) {
38832430d7b7STakashi Iwai 		struct nid_path *path;
38847594aa33STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, pin, PIN_IN);
38852430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
38862430d7b7STakashi Iwai 		if (path)
38872430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
38882430d7b7STakashi Iwai 	}
3889352f7f91STakashi Iwai }
3890352f7f91STakashi Iwai 
3891973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
3892973e4972STakashi Iwai  * invalid unsol tags by some reason
3893973e4972STakashi Iwai  */
3894973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
3895973e4972STakashi Iwai {
3896973e4972STakashi Iwai 	int i;
3897973e4972STakashi Iwai 
3898973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
3899973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
3900973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
3901973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
3902973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
3903973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
3904973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
3905973e4972STakashi Iwai 	}
3906973e4972STakashi Iwai }
3907973e4972STakashi Iwai 
3908352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
3909352f7f91STakashi Iwai {
3910352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3911352f7f91STakashi Iwai 
3912352f7f91STakashi Iwai 	if (spec->init_hook)
3913352f7f91STakashi Iwai 		spec->init_hook(codec);
3914352f7f91STakashi Iwai 
3915352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
3916352f7f91STakashi Iwai 
39173bbcd274STakashi Iwai 	codec->cached_write = 1;
39183bbcd274STakashi Iwai 
3919352f7f91STakashi Iwai 	init_multi_out(codec);
3920352f7f91STakashi Iwai 	init_extra_out(codec);
3921352f7f91STakashi Iwai 	init_multi_io(codec);
3922352f7f91STakashi Iwai 	init_analog_input(codec);
3923352f7f91STakashi Iwai 	init_input_src(codec);
3924352f7f91STakashi Iwai 	init_digital(codec);
3925352f7f91STakashi Iwai 
3926973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
3927973e4972STakashi Iwai 
3928352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
39295d550e15STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
39305d550e15STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
39315d550e15STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
3932352f7f91STakashi Iwai 
39333bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
39343bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
39353bbcd274STakashi Iwai 
3936352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
3937352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
3938352f7f91STakashi Iwai 
3939352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
3940352f7f91STakashi Iwai 	return 0;
3941352f7f91STakashi Iwai }
3942*fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
3943*fce52a3bSTakashi Iwai 
3944*fce52a3bSTakashi Iwai 
3945*fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
3946*fce52a3bSTakashi Iwai {
3947*fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
3948*fce52a3bSTakashi Iwai 	kfree(codec->spec);
3949*fce52a3bSTakashi Iwai 	codec->spec = NULL;
3950*fce52a3bSTakashi Iwai }
3951*fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
3952*fce52a3bSTakashi Iwai 
3953*fce52a3bSTakashi Iwai #ifdef CONFIG_PM
3954*fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3955*fce52a3bSTakashi Iwai {
3956*fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3957*fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3958*fce52a3bSTakashi Iwai }
3959*fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
3960*fce52a3bSTakashi Iwai #endif
3961352f7f91STakashi Iwai 
3962352f7f91STakashi Iwai 
3963352f7f91STakashi Iwai /*
3964352f7f91STakashi Iwai  * the generic codec support
3965352f7f91STakashi Iwai  */
39661da177e4SLinus Torvalds 
3967352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
3968352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
3969352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
3970352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
3971*fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
3972352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
397383012a7cSTakashi Iwai #ifdef CONFIG_PM
3974*fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
3975cb53c626STakashi Iwai #endif
39761da177e4SLinus Torvalds };
39771da177e4SLinus Torvalds 
39781da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
39791da177e4SLinus Torvalds {
3980352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
39811da177e4SLinus Torvalds 	int err;
39821da177e4SLinus Torvalds 
3983e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3984352f7f91STakashi Iwai 	if (!spec)
39851da177e4SLinus Torvalds 		return -ENOMEM;
3986352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
39871da177e4SLinus Torvalds 	codec->spec = spec;
39881da177e4SLinus Torvalds 
39899eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
39909eb413e5STakashi Iwai 	if (err < 0)
39919eb413e5STakashi Iwai 		return err;
39929eb413e5STakashi Iwai 
39939eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
3994352f7f91STakashi Iwai 	if (err < 0)
39951da177e4SLinus Torvalds 		goto error;
39961da177e4SLinus Torvalds 
39971da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
39981da177e4SLinus Torvalds 	return 0;
39991da177e4SLinus Torvalds 
40001da177e4SLinus Torvalds error:
4001*fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
40021da177e4SLinus Torvalds 	return err;
40031da177e4SLinus Torvalds }
4004*fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
4005