xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 973e4972)
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>
271da177e4SLinus Torvalds #include <sound/core.h>
28352f7f91STakashi Iwai #include <sound/jack.h>
291da177e4SLinus Torvalds #include "hda_codec.h"
301da177e4SLinus Torvalds #include "hda_local.h"
31352f7f91STakashi Iwai #include "hda_auto_parser.h"
32352f7f91STakashi Iwai #include "hda_jack.h"
33352f7f91STakashi Iwai #include "hda_generic.h"
341da177e4SLinus Torvalds 
351da177e4SLinus Torvalds 
36352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
37352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
381da177e4SLinus Torvalds {
39352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
40352f7f91STakashi Iwai 	snd_array_init(&spec->bind_ctls, sizeof(struct hda_bind_ctls *), 8);
41352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
42352f7f91STakashi Iwai 	return 0;
43352f7f91STakashi Iwai }
44352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
451da177e4SLinus Torvalds 
4612c93df6STakashi Iwai struct snd_kcontrol_new *
4712c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
48352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
49352f7f91STakashi Iwai {
50352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
51352f7f91STakashi Iwai 	if (!knew)
52352f7f91STakashi Iwai 		return NULL;
53352f7f91STakashi Iwai 	*knew = *temp;
54352f7f91STakashi Iwai 	if (name)
55352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
56352f7f91STakashi Iwai 	else if (knew->name)
57352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
58352f7f91STakashi Iwai 	if (!knew->name)
59352f7f91STakashi Iwai 		return NULL;
60352f7f91STakashi Iwai 	return knew;
61352f7f91STakashi Iwai }
6212c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
63352f7f91STakashi Iwai 
64352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
65352f7f91STakashi Iwai {
66352f7f91STakashi Iwai 	if (spec->kctls.list) {
67352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
68352f7f91STakashi Iwai 		int i;
69352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
70352f7f91STakashi Iwai 			kfree(kctl[i].name);
71352f7f91STakashi Iwai 	}
72352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
73352f7f91STakashi Iwai }
74352f7f91STakashi Iwai 
75352f7f91STakashi Iwai static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
76352f7f91STakashi Iwai 					  unsigned int nums,
77352f7f91STakashi Iwai 					  struct hda_ctl_ops *ops)
78352f7f91STakashi Iwai {
79352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
80352f7f91STakashi Iwai 	struct hda_bind_ctls **ctlp, *ctl;
81352f7f91STakashi Iwai 	ctlp = snd_array_new(&spec->bind_ctls);
82352f7f91STakashi Iwai 	if (!ctlp)
83352f7f91STakashi Iwai 		return NULL;
84352f7f91STakashi Iwai 	ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
85352f7f91STakashi Iwai 	*ctlp = ctl;
86352f7f91STakashi Iwai 	if (ctl)
87352f7f91STakashi Iwai 		ctl->ops = ops;
88352f7f91STakashi Iwai 	return ctl;
89352f7f91STakashi Iwai }
90352f7f91STakashi Iwai 
91352f7f91STakashi Iwai static void free_bind_ctls(struct hda_gen_spec *spec)
92352f7f91STakashi Iwai {
93352f7f91STakashi Iwai 	if (spec->bind_ctls.list) {
94352f7f91STakashi Iwai 		struct hda_bind_ctls **ctl = spec->bind_ctls.list;
95352f7f91STakashi Iwai 		int i;
96352f7f91STakashi Iwai 		for (i = 0; i < spec->bind_ctls.used; i++)
97352f7f91STakashi Iwai 			kfree(ctl[i]);
98352f7f91STakashi Iwai 	}
99352f7f91STakashi Iwai 	snd_array_free(&spec->bind_ctls);
100352f7f91STakashi Iwai }
101352f7f91STakashi Iwai 
102352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
103352f7f91STakashi Iwai {
1041da177e4SLinus Torvalds 	if (!spec)
1051da177e4SLinus Torvalds 		return;
106352f7f91STakashi Iwai 	free_kctls(spec);
107352f7f91STakashi Iwai 	free_bind_ctls(spec);
108352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1091da177e4SLinus Torvalds }
110352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds /*
113352f7f91STakashi Iwai  * parsing paths
1141da177e4SLinus Torvalds  */
1151da177e4SLinus Torvalds 
116352f7f91STakashi Iwai /* get the path between the given NIDs;
117352f7f91STakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
1181da177e4SLinus Torvalds  */
119352f7f91STakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
120352f7f91STakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
1211da177e4SLinus Torvalds {
122352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
123352f7f91STakashi Iwai 	int i;
1241da177e4SLinus Torvalds 
125352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
126352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
127352f7f91STakashi Iwai 		if (path->depth <= 0)
128352f7f91STakashi Iwai 			continue;
129352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
130352f7f91STakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid))
131352f7f91STakashi Iwai 			return path;
1321da177e4SLinus Torvalds 	}
1331da177e4SLinus Torvalds 	return NULL;
1341da177e4SLinus Torvalds }
135352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
1361da177e4SLinus Torvalds 
137352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
138352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
1391da177e4SLinus Torvalds {
140352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
141352f7f91STakashi Iwai 	int i;
142352f7f91STakashi Iwai 
143352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
144352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
145352f7f91STakashi Iwai 		if (path->path[0] == nid)
146352f7f91STakashi Iwai 			return true;
147352f7f91STakashi Iwai 	}
148352f7f91STakashi Iwai 	return false;
1491da177e4SLinus Torvalds }
1501da177e4SLinus Torvalds 
151352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
152352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
153352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
1541da177e4SLinus Torvalds {
155352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
156352f7f91STakashi Iwai 		return false;
157352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
1581da177e4SLinus Torvalds }
1591da177e4SLinus Torvalds 
160352f7f91STakashi Iwai /* nid, dir and idx */
161352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
162352f7f91STakashi Iwai 
163352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
164352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
1651da177e4SLinus Torvalds {
166352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
167352f7f91STakashi Iwai 	int i;
168352f7f91STakashi Iwai 
169352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
170352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
171352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
172352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
173352f7f91STakashi Iwai 			return true;
174352f7f91STakashi Iwai 	}
175352f7f91STakashi Iwai 	return false;
1761da177e4SLinus Torvalds }
1771da177e4SLinus Torvalds 
178352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
179352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
180cb53c626STakashi Iwai 			      int dir, int idx)
181cb53c626STakashi Iwai {
182352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
183352f7f91STakashi Iwai 	return is_ctl_used(codec, val, NID_PATH_VOL_CTL) ||
184352f7f91STakashi Iwai 		is_ctl_used(codec, val, NID_PATH_MUTE_CTL);
185cb53c626STakashi Iwai }
186352f7f91STakashi Iwai 
187352f7f91STakashi Iwai /* called recursively */
188352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
189352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
190352f7f91STakashi Iwai 			     int with_aa_mix, struct nid_path *path, int depth)
191352f7f91STakashi Iwai {
192352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
193352f7f91STakashi Iwai 	hda_nid_t conn[16];
194352f7f91STakashi Iwai 	int i, nums;
195352f7f91STakashi Iwai 
196352f7f91STakashi Iwai 	if (to_nid == spec->mixer_nid) {
197352f7f91STakashi Iwai 		if (!with_aa_mix)
198352f7f91STakashi Iwai 			return false;
199352f7f91STakashi Iwai 		with_aa_mix = 2; /* mark aa-mix is included */
200352f7f91STakashi Iwai 	}
201352f7f91STakashi Iwai 
202352f7f91STakashi Iwai 	nums = snd_hda_get_connections(codec, to_nid, conn, ARRAY_SIZE(conn));
203352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
204352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
205352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
206352f7f91STakashi Iwai 			 * try to find an empty DAC
207352f7f91STakashi Iwai 			 */
208352f7f91STakashi Iwai 			if (from_nid ||
209352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
210352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
211352f7f91STakashi Iwai 				continue;
212352f7f91STakashi Iwai 		}
213352f7f91STakashi Iwai 		/* aa-mix is requested but not included? */
214352f7f91STakashi Iwai 		if (!(spec->mixer_nid && with_aa_mix == 1))
215352f7f91STakashi Iwai 			goto found;
216352f7f91STakashi Iwai 	}
217352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
218352f7f91STakashi Iwai 		return false;
219352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
220352f7f91STakashi Iwai 		unsigned int type;
221352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
222352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
223352f7f91STakashi Iwai 		    type == AC_WID_PIN)
224352f7f91STakashi Iwai 			continue;
225352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
226352f7f91STakashi Iwai 				     with_aa_mix, path, depth + 1))
227352f7f91STakashi Iwai 			goto found;
228352f7f91STakashi Iwai 	}
229352f7f91STakashi Iwai 	return false;
230352f7f91STakashi Iwai 
231352f7f91STakashi Iwai  found:
232352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
233352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
234352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
235352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
236352f7f91STakashi Iwai 	path->depth++;
237352f7f91STakashi Iwai 	return true;
238352f7f91STakashi Iwai }
239352f7f91STakashi Iwai 
240352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
241352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
242352f7f91STakashi Iwai  * when @with_aa_mix is 0, paths with spec->mixer_nid are excluded.
243352f7f91STakashi Iwai  * when @with_aa_mix is 1, paths without spec->mixer_nid are excluded.
244352f7f91STakashi Iwai  * when @with_aa_mix is 2, no special handling about spec->mixer_nid.
245352f7f91STakashi Iwai  */
246352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
247352f7f91STakashi Iwai 			    hda_nid_t to_nid, int with_aa_mix,
248352f7f91STakashi Iwai 			    struct nid_path *path)
249352f7f91STakashi Iwai {
250352f7f91STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path, 1)) {
251352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
252352f7f91STakashi Iwai 		path->depth++;
253352f7f91STakashi Iwai #if 0
254352f7f91STakashi Iwai 		snd_printdd("path: depth=%d, %02x/%02x/%02x/%02x/%02x\n",
255352f7f91STakashi Iwai 			    path->depth, path->path[0], path->path[1],
256352f7f91STakashi Iwai 			    path->path[2], path->path[3], path->path[4]);
257352f7f91STakashi Iwai #endif
258352f7f91STakashi Iwai 		return true;
259352f7f91STakashi Iwai 	}
260352f7f91STakashi Iwai 	return false;
261352f7f91STakashi Iwai }
262352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
263352f7f91STakashi Iwai 
264352f7f91STakashi Iwai /*
265352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
266352f7f91STakashi Iwai  * if no valid path is found, return NULL
267352f7f91STakashi Iwai  */
268352f7f91STakashi Iwai struct nid_path *
269352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
270352f7f91STakashi Iwai 		     hda_nid_t to_nid, int with_aa_mix)
271352f7f91STakashi Iwai {
272352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
273352f7f91STakashi Iwai 	struct nid_path *path;
274352f7f91STakashi Iwai 
275352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
276352f7f91STakashi Iwai 		return NULL;
277352f7f91STakashi Iwai 
278352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
279352f7f91STakashi Iwai 	if (!path)
280352f7f91STakashi Iwai 		return NULL;
281352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
282352f7f91STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, with_aa_mix, path))
283352f7f91STakashi Iwai 		return path;
284352f7f91STakashi Iwai 	/* push back */
285352f7f91STakashi Iwai 	spec->paths.used--;
286352f7f91STakashi Iwai 	return NULL;
287352f7f91STakashi Iwai }
288352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
289352f7f91STakashi Iwai 
290352f7f91STakashi Iwai /* look for an empty DAC slot */
291352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
292352f7f91STakashi Iwai 			      bool is_digital)
293352f7f91STakashi Iwai {
294352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
295352f7f91STakashi Iwai 	bool cap_digital;
296352f7f91STakashi Iwai 	int i;
297352f7f91STakashi Iwai 
298352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
299352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
300352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
301352f7f91STakashi Iwai 			continue;
302352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
303352f7f91STakashi Iwai 		if (is_digital != cap_digital)
304352f7f91STakashi Iwai 			continue;
305352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
306352f7f91STakashi Iwai 			return nid;
307352f7f91STakashi Iwai 	}
308352f7f91STakashi Iwai 	return 0;
309352f7f91STakashi Iwai }
310352f7f91STakashi Iwai 
311352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
312352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
313352f7f91STakashi Iwai {
314352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
315352f7f91STakashi Iwai 	val |= chs << 16;
316352f7f91STakashi Iwai 	return val;
317352f7f91STakashi Iwai }
318352f7f91STakashi Iwai 
319352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
320352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
321352f7f91STakashi Iwai 			   int dir, unsigned int bits)
322352f7f91STakashi Iwai {
323352f7f91STakashi Iwai 	if (!nid)
324352f7f91STakashi Iwai 		return false;
325352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
326352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
327352f7f91STakashi Iwai 			return true;
328352f7f91STakashi Iwai 	return false;
329352f7f91STakashi Iwai }
330352f7f91STakashi Iwai 
331352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
332352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
333352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
334352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
335352f7f91STakashi Iwai 
336352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
337352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
338352f7f91STakashi Iwai 				       struct nid_path *path)
339352f7f91STakashi Iwai {
340352f7f91STakashi Iwai 	int i;
341352f7f91STakashi Iwai 
342352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
343352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
344352f7f91STakashi Iwai 			return path->path[i];
345352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
346352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
347352f7f91STakashi Iwai 			return path->path[i];
348352f7f91STakashi Iwai 	}
349352f7f91STakashi Iwai 	return 0;
350352f7f91STakashi Iwai }
351352f7f91STakashi Iwai 
352352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
353352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
354352f7f91STakashi Iwai 				      struct nid_path *path)
355352f7f91STakashi Iwai {
356352f7f91STakashi Iwai 	int i;
357352f7f91STakashi Iwai 
358352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
359352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
360352f7f91STakashi Iwai 			return path->path[i];
361352f7f91STakashi Iwai 	}
362352f7f91STakashi Iwai 	return 0;
363352f7f91STakashi Iwai }
364352f7f91STakashi Iwai 
365352f7f91STakashi Iwai /*
366352f7f91STakashi Iwai  * path activation / deactivation
367352f7f91STakashi Iwai  */
368352f7f91STakashi Iwai 
369352f7f91STakashi Iwai /* can have the amp-in capability? */
370352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
371352f7f91STakashi Iwai {
372352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
373352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
374352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
375352f7f91STakashi Iwai 
376352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
377352f7f91STakashi Iwai 		return false;
378352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
379352f7f91STakashi Iwai 		return false;
380352f7f91STakashi Iwai 	return true;
381352f7f91STakashi Iwai }
382352f7f91STakashi Iwai 
383352f7f91STakashi Iwai /* can have the amp-out capability? */
384352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
385352f7f91STakashi Iwai {
386352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
387352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
388352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
389352f7f91STakashi Iwai 
390352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
391352f7f91STakashi Iwai 		return false;
392352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
393352f7f91STakashi Iwai 		return false;
394352f7f91STakashi Iwai 	return true;
395352f7f91STakashi Iwai }
396352f7f91STakashi Iwai 
397352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
398352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
399352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
400352f7f91STakashi Iwai {
401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
402352f7f91STakashi Iwai 	int i, n;
403352f7f91STakashi Iwai 
404352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
405352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
406352f7f91STakashi Iwai 		if (!path->active)
407352f7f91STakashi Iwai 			continue;
408352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
409352f7f91STakashi Iwai 			if (path->path[i] == nid) {
410352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
411352f7f91STakashi Iwai 					return true;
412352f7f91STakashi Iwai 				break;
413352f7f91STakashi Iwai 			}
414352f7f91STakashi Iwai 		}
415352f7f91STakashi Iwai 	}
416352f7f91STakashi Iwai 	return false;
417352f7f91STakashi Iwai }
418352f7f91STakashi Iwai 
419352f7f91STakashi Iwai /* get the default amp value for the target state */
420352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
421352f7f91STakashi Iwai 				   int dir, bool enable)
422352f7f91STakashi Iwai {
423352f7f91STakashi Iwai 	unsigned int caps;
424352f7f91STakashi Iwai 	unsigned int val = 0;
425352f7f91STakashi Iwai 
426352f7f91STakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
427352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
428352f7f91STakashi Iwai 		/* set to 0dB */
429352f7f91STakashi Iwai 		if (enable)
430352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
431352f7f91STakashi Iwai 	}
432352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
433352f7f91STakashi Iwai 		if (!enable)
434352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
435352f7f91STakashi Iwai 	}
436352f7f91STakashi Iwai 	return val;
437352f7f91STakashi Iwai }
438352f7f91STakashi Iwai 
439352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
440352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
441352f7f91STakashi Iwai {
442352f7f91STakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, false);
443352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
444352f7f91STakashi Iwai }
445352f7f91STakashi Iwai 
446352f7f91STakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
447352f7f91STakashi Iwai 			 int idx, bool enable)
448352f7f91STakashi Iwai {
449352f7f91STakashi Iwai 	int val;
450352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, dir, idx) ||
451352f7f91STakashi Iwai 	    is_active_nid(codec, nid, dir, idx))
452352f7f91STakashi Iwai 		return;
453352f7f91STakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, enable);
454352f7f91STakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, 0xff, val);
455352f7f91STakashi Iwai }
456352f7f91STakashi Iwai 
457352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
458352f7f91STakashi Iwai 			     int i, bool enable)
459352f7f91STakashi Iwai {
460352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
461352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
462352f7f91STakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, enable);
463352f7f91STakashi Iwai }
464352f7f91STakashi Iwai 
465352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
466352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
467352f7f91STakashi Iwai {
468352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
469352f7f91STakashi Iwai 	hda_nid_t conn[16];
470352f7f91STakashi Iwai 	int n, nums, idx;
471352f7f91STakashi Iwai 	int type;
472352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
473352f7f91STakashi Iwai 
474352f7f91STakashi Iwai 	nums = snd_hda_get_connections(codec, nid, conn, ARRAY_SIZE(conn));
475352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
476352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
477352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
478352f7f91STakashi Iwai 		nums = 1;
479352f7f91STakashi Iwai 		idx = 0;
480352f7f91STakashi Iwai 	} else
481352f7f91STakashi Iwai 		idx = path->idx[i];
482352f7f91STakashi Iwai 
483352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
484352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
485352f7f91STakashi Iwai 
486352f7f91STakashi Iwai 	if (is_ctl_associated(codec, nid, HDA_INPUT, idx))
487352f7f91STakashi Iwai 		return;
488352f7f91STakashi Iwai 
489352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
490352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
491352f7f91STakashi Iwai 	 */
492352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
493352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
494352f7f91STakashi Iwai 			continue;
495352f7f91STakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, enable);
496352f7f91STakashi Iwai 	}
497352f7f91STakashi Iwai }
498352f7f91STakashi Iwai 
499352f7f91STakashi Iwai /* activate or deactivate the given path
500352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
501352f7f91STakashi Iwai  */
502352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
503352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
504352f7f91STakashi Iwai {
505352f7f91STakashi Iwai 	int i;
506352f7f91STakashi Iwai 
507352f7f91STakashi Iwai 	if (!enable)
508352f7f91STakashi Iwai 		path->active = false;
509352f7f91STakashi Iwai 
510352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
511352f7f91STakashi Iwai 		if (enable && path->multi[i])
512352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
513352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
514352f7f91STakashi Iwai 					    path->idx[i]);
515352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
516352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
517352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
518352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
519352f7f91STakashi Iwai 	}
520352f7f91STakashi Iwai 
521352f7f91STakashi Iwai 	if (enable)
522352f7f91STakashi Iwai 		path->active = true;
523352f7f91STakashi Iwai }
524352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
525352f7f91STakashi Iwai 
526352f7f91STakashi Iwai 
527352f7f91STakashi Iwai /*
528352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
529352f7f91STakashi Iwai  */
530352f7f91STakashi Iwai 
531352f7f91STakashi Iwai enum {
532352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
533352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
534352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
535352f7f91STakashi Iwai 	HDA_CTL_BIND_VOL,
536352f7f91STakashi Iwai 	HDA_CTL_BIND_SW,
537352f7f91STakashi Iwai };
538352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
539352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
540352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
541352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
542352f7f91STakashi Iwai 	HDA_BIND_VOL(NULL, 0),
543352f7f91STakashi Iwai 	HDA_BIND_SW(NULL, 0),
544352f7f91STakashi Iwai };
545352f7f91STakashi Iwai 
546352f7f91STakashi Iwai /* add dynamic controls from template */
547352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
548352f7f91STakashi Iwai 		       int cidx, unsigned long val)
549352f7f91STakashi Iwai {
550352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
551352f7f91STakashi Iwai 
55212c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
553352f7f91STakashi Iwai 	if (!knew)
554352f7f91STakashi Iwai 		return -ENOMEM;
555352f7f91STakashi Iwai 	knew->index = cidx;
556352f7f91STakashi Iwai 	if (get_amp_nid_(val))
557352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
558352f7f91STakashi Iwai 	knew->private_value = val;
559352f7f91STakashi Iwai 	return 0;
560352f7f91STakashi Iwai }
561352f7f91STakashi Iwai 
562352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
563352f7f91STakashi Iwai 				const char *pfx, const char *dir,
564352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
565352f7f91STakashi Iwai {
566352f7f91STakashi Iwai 	char name[32];
567352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
568352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
569352f7f91STakashi Iwai }
570352f7f91STakashi Iwai 
571352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
572352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
573352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
574352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
575352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
576352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
577352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
578352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
579352f7f91STakashi Iwai 
580352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
581352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
582352f7f91STakashi Iwai {
583352f7f91STakashi Iwai 	unsigned int val;
584352f7f91STakashi Iwai 	if (!path)
585352f7f91STakashi Iwai 		return 0;
586352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
587352f7f91STakashi Iwai 	if (!val)
588352f7f91STakashi Iwai 		return 0;
589352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
590352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
591352f7f91STakashi Iwai }
592352f7f91STakashi Iwai 
593352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
594352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
595352f7f91STakashi Iwai 			       int type)
596352f7f91STakashi Iwai {
597352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
598352f7f91STakashi Iwai 	if (path) {
599352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
600352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
601352f7f91STakashi Iwai 			chs = 3; /* stereo */
602352f7f91STakashi Iwai 	}
603352f7f91STakashi Iwai 	return chs;
604352f7f91STakashi Iwai }
605352f7f91STakashi Iwai 
606352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
607352f7f91STakashi Iwai 			  struct nid_path *path)
608352f7f91STakashi Iwai {
609352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
610352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
611352f7f91STakashi Iwai }
612352f7f91STakashi Iwai 
613352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
614352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
615352f7f91STakashi Iwai  */
616352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
617352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
618352f7f91STakashi Iwai {
619352f7f91STakashi Iwai 	unsigned int val;
620352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
621352f7f91STakashi Iwai 
622352f7f91STakashi Iwai 	if (!path)
623352f7f91STakashi Iwai 		return 0;
624352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
625352f7f91STakashi Iwai 	if (!val)
626352f7f91STakashi Iwai 		return 0;
627352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
628352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
629352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
630352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
631352f7f91STakashi Iwai 		if (nums > 1) {
632352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
633352f7f91STakashi Iwai 			val |= nums << 19;
634352f7f91STakashi Iwai 		}
635352f7f91STakashi Iwai 	}
636352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
637352f7f91STakashi Iwai }
638352f7f91STakashi Iwai 
639352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
640352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
641352f7f91STakashi Iwai {
642352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
643352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
644352f7f91STakashi Iwai }
645352f7f91STakashi Iwai 
646352f7f91STakashi Iwai static const char * const channel_name[4] = {
647352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
648352f7f91STakashi Iwai };
649352f7f91STakashi Iwai 
650352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
651352f7f91STakashi Iwai static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch,
652352f7f91STakashi Iwai 				    bool can_be_master, int *index)
653352f7f91STakashi Iwai {
654352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
655352f7f91STakashi Iwai 
656352f7f91STakashi Iwai 	*index = 0;
657352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
658352f7f91STakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
659352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
660352f7f91STakashi Iwai 
661352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
662352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
663352f7f91STakashi Iwai 	 */
664352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
665352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
666352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
667352f7f91STakashi Iwai 
668352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
669352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
670352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
671352f7f91STakashi Iwai 			return "Speaker";
672352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
673352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
674352f7f91STakashi Iwai 		break;
675352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
676352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
677352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
678352f7f91STakashi Iwai 			break;
679352f7f91STakashi Iwai 		*index = ch;
680352f7f91STakashi Iwai 		return "Headphone";
681352f7f91STakashi Iwai 	default:
682352f7f91STakashi Iwai 		if (cfg->line_outs == 1 && !spec->multi_ios)
683352f7f91STakashi Iwai 			return "PCM";
684352f7f91STakashi Iwai 		break;
685352f7f91STakashi Iwai 	}
686352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
687352f7f91STakashi Iwai 		snd_BUG();
688352f7f91STakashi Iwai 		return "PCM";
689352f7f91STakashi Iwai 	}
690352f7f91STakashi Iwai 
691352f7f91STakashi Iwai 	return channel_name[ch];
692352f7f91STakashi Iwai }
693352f7f91STakashi Iwai 
694352f7f91STakashi Iwai /*
695352f7f91STakashi Iwai  * Parse output paths
696352f7f91STakashi Iwai  */
697352f7f91STakashi Iwai 
698352f7f91STakashi Iwai /* badness definition */
699352f7f91STakashi Iwai enum {
700352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
701352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
702352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
703352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
704352f7f91STakashi Iwai 	/* No possible multi-ios */
705352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
706352f7f91STakashi Iwai 	/* No individual DAC for extra output */
707352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
708352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
709352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
710352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
711352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
712352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
713352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
714352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
715352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
716352f7f91STakashi Iwai 	/* Volume widget is shared */
717352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
718352f7f91STakashi Iwai };
719352f7f91STakashi Iwai 
720352f7f91STakashi Iwai /* look for widgets in the path between the given NIDs appropriate for
721352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
722352f7f91STakashi Iwai  *
723352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
724352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
725352f7f91STakashi Iwai  * total badness for both volume and mute controls.
726352f7f91STakashi Iwai  */
727352f7f91STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, hda_nid_t pin,
728352f7f91STakashi Iwai 				hda_nid_t dac)
729352f7f91STakashi Iwai {
730352f7f91STakashi Iwai 	struct nid_path *path = snd_hda_get_nid_path(codec, dac, pin);
731352f7f91STakashi Iwai 	hda_nid_t nid;
732352f7f91STakashi Iwai 	unsigned int val;
733352f7f91STakashi Iwai 	int badness = 0;
734352f7f91STakashi Iwai 
735352f7f91STakashi Iwai 	if (!path)
736352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
737352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
738352f7f91STakashi Iwai 	if (nid) {
739352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
740352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
741352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
742352f7f91STakashi Iwai 		else
743352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
744352f7f91STakashi Iwai 	} else
745352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
746352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
747352f7f91STakashi Iwai 	if (nid) {
748352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
749352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
750352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
751352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
752352f7f91STakashi Iwai 		else
753352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
754352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
755352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
756352f7f91STakashi Iwai 		else
757352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
758352f7f91STakashi Iwai 	} else
759352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
760352f7f91STakashi Iwai 	return badness;
761352f7f91STakashi Iwai }
762352f7f91STakashi Iwai 
763352f7f91STakashi Iwai struct badness_table {
764352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
765352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
766352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
767352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
768352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
769352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
770352f7f91STakashi Iwai };
771352f7f91STakashi Iwai 
772352f7f91STakashi Iwai static struct badness_table main_out_badness = {
773352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
774352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
775352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
776352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
777352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
778352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
779352f7f91STakashi Iwai };
780352f7f91STakashi Iwai 
781352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
782352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
783352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
784352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
785352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
786352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
787352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
788352f7f91STakashi Iwai };
789352f7f91STakashi Iwai 
790352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
791352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
792352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
793352f7f91STakashi Iwai 			   const struct badness_table *bad)
794352f7f91STakashi Iwai {
795352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
796352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
797352f7f91STakashi Iwai 	int i, j;
798352f7f91STakashi Iwai 	int badness = 0;
799352f7f91STakashi Iwai 	hda_nid_t dac;
800352f7f91STakashi Iwai 
801352f7f91STakashi Iwai 	if (!num_outs)
802352f7f91STakashi Iwai 		return 0;
803352f7f91STakashi Iwai 
804352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
805352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
806352f7f91STakashi Iwai 		if (!dacs[i])
807352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
808352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
809352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
810352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
811352f7f91STakashi Iwai 					dacs[0] = dacs[j];
812352f7f91STakashi Iwai 					dacs[j] = 0;
813352f7f91STakashi Iwai 					break;
814352f7f91STakashi Iwai 				}
815352f7f91STakashi Iwai 			}
816352f7f91STakashi Iwai 		}
817352f7f91STakashi Iwai 		dac = dacs[i];
818352f7f91STakashi Iwai 		if (!dac) {
819352f7f91STakashi Iwai 			if (is_reachable_path(codec, dacs[0], pin))
820352f7f91STakashi Iwai 				dac = dacs[0];
821352f7f91STakashi Iwai 			else if (cfg->line_outs > i &&
822352f7f91STakashi Iwai 				 is_reachable_path(codec, spec->private_dac_nids[i], pin))
823352f7f91STakashi Iwai 				dac = spec->private_dac_nids[i];
824352f7f91STakashi Iwai 			if (dac) {
825352f7f91STakashi Iwai 				if (!i)
826352f7f91STakashi Iwai 					badness += bad->shared_primary;
827352f7f91STakashi Iwai 				else if (i == 1)
828352f7f91STakashi Iwai 					badness += bad->shared_surr;
829352f7f91STakashi Iwai 				else
830352f7f91STakashi Iwai 					badness += bad->shared_clfe;
831352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
832352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
833352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
834352f7f91STakashi Iwai 			} else if (!i)
835352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
836352f7f91STakashi Iwai 			else
837352f7f91STakashi Iwai 				badness += bad->no_dac;
838352f7f91STakashi Iwai 		}
839352f7f91STakashi Iwai 		if (!snd_hda_add_new_path(codec, dac, pin, 0))
840352f7f91STakashi Iwai 			dac = dacs[i] = 0;
841352f7f91STakashi Iwai 		if (dac)
842352f7f91STakashi Iwai 			badness += assign_out_path_ctls(codec, pin, dac);
843352f7f91STakashi Iwai 	}
844352f7f91STakashi Iwai 
845352f7f91STakashi Iwai 	return badness;
846352f7f91STakashi Iwai }
847352f7f91STakashi Iwai 
848352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
849352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
850352f7f91STakashi Iwai {
851352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
852352f7f91STakashi Iwai 	int i;
853352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
854352f7f91STakashi Iwai 
855352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
856352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
857352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
858352f7f91STakashi Iwai 			continue;
859352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
860352f7f91STakashi Iwai 			if (nid_found)
861352f7f91STakashi Iwai 				return 0;
862352f7f91STakashi Iwai 			nid_found = nid;
863352f7f91STakashi Iwai 		}
864352f7f91STakashi Iwai 	}
865352f7f91STakashi Iwai 	return nid_found;
866352f7f91STakashi Iwai }
867352f7f91STakashi Iwai 
868352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
869352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
870352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
871352f7f91STakashi Iwai {
872352f7f91STakashi Iwai 	unsigned int defcfg, caps;
873352f7f91STakashi Iwai 
874352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
875352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
876352f7f91STakashi Iwai 		return false;
877352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
878352f7f91STakashi Iwai 		return false;
879352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
880352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
881352f7f91STakashi Iwai 		return false;
882352f7f91STakashi Iwai 	return true;
883352f7f91STakashi Iwai }
884352f7f91STakashi Iwai 
885352f7f91STakashi Iwai /*
886352f7f91STakashi Iwai  * multi-io helper
887352f7f91STakashi Iwai  *
888352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
889352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
890352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
891352f7f91STakashi Iwai  * the badness value.
892352f7f91STakashi Iwai  */
893352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
894352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
895352f7f91STakashi Iwai 			  bool hardwired, int offset)
896352f7f91STakashi Iwai {
897352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
898352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
899352f7f91STakashi Iwai 	int type, i, j, dacs, num_pins, old_pins;
900352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
901352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
902352f7f91STakashi Iwai 	int badness = 0;
903352f7f91STakashi Iwai 
904352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
905352f7f91STakashi Iwai 	if (old_pins >= 2)
906352f7f91STakashi Iwai 		goto end_fill;
907352f7f91STakashi Iwai 
908352f7f91STakashi Iwai 	num_pins = 0;
909352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
910352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
911352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
912352f7f91STakashi Iwai 				continue;
913352f7f91STakashi Iwai 			if (can_be_multiio_pin(codec, location,
914352f7f91STakashi Iwai 					       cfg->inputs[i].pin))
915352f7f91STakashi Iwai 				num_pins++;
916352f7f91STakashi Iwai 		}
917352f7f91STakashi Iwai 	}
918352f7f91STakashi Iwai 	if (num_pins < 2)
919352f7f91STakashi Iwai 		goto end_fill;
920352f7f91STakashi Iwai 
921352f7f91STakashi Iwai 	dacs = spec->multiout.num_dacs;
922352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
923352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
924352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
925352f7f91STakashi Iwai 			hda_nid_t dac = 0;
926352f7f91STakashi Iwai 
927352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
928352f7f91STakashi Iwai 				continue;
929352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
930352f7f91STakashi Iwai 				continue;
931352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
932352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
933352f7f91STakashi Iwai 					break;
934352f7f91STakashi Iwai 			}
935352f7f91STakashi Iwai 			if (j < spec->multi_ios)
936352f7f91STakashi Iwai 				continue;
937352f7f91STakashi Iwai 
938352f7f91STakashi Iwai 			if (offset && offset + spec->multi_ios < dacs) {
939352f7f91STakashi Iwai 				dac = spec->private_dac_nids[offset + spec->multi_ios];
940352f7f91STakashi Iwai 				if (!is_reachable_path(codec, dac, nid))
941352f7f91STakashi Iwai 					dac = 0;
942352f7f91STakashi Iwai 			}
943352f7f91STakashi Iwai 			if (hardwired)
944352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
945352f7f91STakashi Iwai 			else if (!dac)
946352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
947352f7f91STakashi Iwai 			if (!dac) {
948352f7f91STakashi Iwai 				badness++;
949352f7f91STakashi Iwai 				continue;
950352f7f91STakashi Iwai 			}
951352f7f91STakashi Iwai 			if (!snd_hda_add_new_path(codec, dac, nid, 0)) {
952352f7f91STakashi Iwai 				badness++;
953352f7f91STakashi Iwai 				continue;
954352f7f91STakashi Iwai 			}
955352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
956352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
957352f7f91STakashi Iwai 			spec->multi_ios++;
958352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
959352f7f91STakashi Iwai 				break;
960352f7f91STakashi Iwai 		}
961352f7f91STakashi Iwai 	}
962352f7f91STakashi Iwai  end_fill:
963352f7f91STakashi Iwai 	if (badness)
964352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
965352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
966352f7f91STakashi Iwai 		if (hardwired)
967352f7f91STakashi Iwai 			return 1; /* nothing found */
968352f7f91STakashi Iwai 		else
969352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
970352f7f91STakashi Iwai 	}
971352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
972352f7f91STakashi Iwai 		/* cancel newly assigned paths */
973352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
974352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
975352f7f91STakashi Iwai 		return badness;
976352f7f91STakashi Iwai 	}
977352f7f91STakashi Iwai 
978352f7f91STakashi Iwai 	/* assign volume and mute controls */
979352f7f91STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++)
980352f7f91STakashi Iwai 		badness += assign_out_path_ctls(codec, spec->multi_io[i].pin,
981352f7f91STakashi Iwai 						spec->multi_io[i].dac);
982352f7f91STakashi Iwai 
983352f7f91STakashi Iwai 	return badness;
984352f7f91STakashi Iwai }
985352f7f91STakashi Iwai 
986352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
987352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
988352f7f91STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs)
989352f7f91STakashi Iwai {
990352f7f91STakashi Iwai 	int i;
991352f7f91STakashi Iwai 	bool found = false;
992352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
993352f7f91STakashi Iwai 		hda_nid_t dac;
994352f7f91STakashi Iwai 		if (dacs[i])
995352f7f91STakashi Iwai 			continue;
996352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
997352f7f91STakashi Iwai 		if (!dac)
998352f7f91STakashi Iwai 			continue;
999352f7f91STakashi Iwai 		if (snd_hda_add_new_path(codec, dac, pins[i], 0)) {
1000352f7f91STakashi Iwai 			dacs[i] = dac;
1001352f7f91STakashi Iwai 			found = true;
1002352f7f91STakashi Iwai 		}
1003352f7f91STakashi Iwai 	}
1004352f7f91STakashi Iwai 	return found;
1005352f7f91STakashi Iwai }
1006352f7f91STakashi Iwai 
1007352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1008352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1009352f7f91STakashi Iwai 			      bool fill_hardwired,
1010352f7f91STakashi Iwai 			      bool fill_mio_first)
1011352f7f91STakashi Iwai {
1012352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1013352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1014352f7f91STakashi Iwai 	int i, err, badness;
1015352f7f91STakashi Iwai 
1016352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1017352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1018352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1019352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1020352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1021352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1022352f7f91STakashi Iwai 	spec->multi_ios = 0;
1023352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1024352f7f91STakashi Iwai 	badness = 0;
1025352f7f91STakashi Iwai 
1026352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1027352f7f91STakashi Iwai 	if (fill_hardwired) {
1028352f7f91STakashi Iwai 		bool mapped;
1029352f7f91STakashi Iwai 		do {
1030352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1031352f7f91STakashi Iwai 					     cfg->line_out_pins,
1032352f7f91STakashi Iwai 					     spec->private_dac_nids);
1033352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1034352f7f91STakashi Iwai 					      cfg->hp_pins,
1035352f7f91STakashi Iwai 					      spec->multiout.hp_out_nid);
1036352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1037352f7f91STakashi Iwai 					      cfg->speaker_pins,
1038352f7f91STakashi Iwai 					      spec->multiout.extra_out_nid);
1039352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1040352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1041352f7f91STakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
1042352f7f91STakashi Iwai 				if (!err)
1043352f7f91STakashi Iwai 					mapped = true;
1044352f7f91STakashi Iwai 			}
1045352f7f91STakashi Iwai 		} while (mapped);
1046352f7f91STakashi Iwai 	}
1047352f7f91STakashi Iwai 
1048352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1049352f7f91STakashi Iwai 				   spec->private_dac_nids,
1050352f7f91STakashi Iwai 				   &main_out_badness);
1051352f7f91STakashi Iwai 
1052352f7f91STakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1053352f7f91STakashi Iwai 	spec->multiout.num_dacs = 0;
1054352f7f91STakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1055352f7f91STakashi Iwai 		if (spec->private_dac_nids[i])
1056352f7f91STakashi Iwai 			spec->multiout.num_dacs++;
1057352f7f91STakashi Iwai 		else {
1058352f7f91STakashi Iwai 			memmove(spec->private_dac_nids + i,
1059352f7f91STakashi Iwai 				spec->private_dac_nids + i + 1,
1060352f7f91STakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1061352f7f91STakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1062352f7f91STakashi Iwai 		}
1063352f7f91STakashi Iwai 	}
1064352f7f91STakashi Iwai 
1065352f7f91STakashi Iwai 	if (fill_mio_first &&
1066352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1067352f7f91STakashi Iwai 		/* try to fill multi-io first */
1068352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
1069352f7f91STakashi Iwai 		if (err < 0)
1070352f7f91STakashi Iwai 			return err;
1071352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1072352f7f91STakashi Iwai 	}
1073352f7f91STakashi Iwai 
1074352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1075352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1076352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1077352f7f91STakashi Iwai 				      &extra_out_badness);
1078352f7f91STakashi Iwai 		if (err < 0)
1079352f7f91STakashi Iwai 			return err;
1080352f7f91STakashi Iwai 		badness += err;
1081352f7f91STakashi Iwai 	}
1082352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1083352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1084352f7f91STakashi Iwai 				      cfg->speaker_pins,
1085352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1086352f7f91STakashi Iwai 					 &extra_out_badness);
1087352f7f91STakashi Iwai 		if (err < 0)
1088352f7f91STakashi Iwai 			return err;
1089352f7f91STakashi Iwai 		badness += err;
1090352f7f91STakashi Iwai 	}
1091352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1092352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
1093352f7f91STakashi Iwai 		if (err < 0)
1094352f7f91STakashi Iwai 			return err;
1095352f7f91STakashi Iwai 		badness += err;
1096352f7f91STakashi Iwai 	}
1097352f7f91STakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1098352f7f91STakashi Iwai 		/* try multi-ios with HP + inputs */
1099352f7f91STakashi Iwai 		int offset = 0;
1100352f7f91STakashi Iwai 		if (cfg->line_outs >= 3)
1101352f7f91STakashi Iwai 			offset = 1;
1102352f7f91STakashi Iwai 		err = fill_multi_ios(codec, cfg->hp_pins[0], false, offset);
1103352f7f91STakashi Iwai 		if (err < 0)
1104352f7f91STakashi Iwai 			return err;
1105352f7f91STakashi Iwai 		badness += err;
1106352f7f91STakashi Iwai 	}
1107352f7f91STakashi Iwai 
1108352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1109352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1110352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1111352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1112352f7f91STakashi Iwai 		spec->ext_channel_count = 2;
1113352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1114352f7f91STakashi Iwai 		spec->multi_ios = 0;
1115352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1116352f7f91STakashi Iwai 	}
1117352f7f91STakashi Iwai 
1118352f7f91STakashi Iwai 	return badness;
1119352f7f91STakashi Iwai }
1120352f7f91STakashi Iwai 
1121352f7f91STakashi Iwai #define DEBUG_BADNESS
1122352f7f91STakashi Iwai 
1123352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1124352f7f91STakashi Iwai #define debug_badness	snd_printdd
1125352f7f91STakashi Iwai #else
1126352f7f91STakashi Iwai #define debug_badness(...)
1127352f7f91STakashi Iwai #endif
1128352f7f91STakashi Iwai 
1129352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1130352f7f91STakashi Iwai {
1131352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1132352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1133352f7f91STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[2],
1134352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1135352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1136352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1137352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1138352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1139352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1140352f7f91STakashi Iwai 			      spec->multi_ios,
1141352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1142352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1143352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1144352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1145352f7f91STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[2],
1146352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1147352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1148352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1149352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1150352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1151352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1152352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1153352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1154352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1155352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1156352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1157352f7f91STakashi Iwai }
1158352f7f91STakashi Iwai 
1159352f7f91STakashi Iwai /* find all available DACs of the codec */
1160352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1161352f7f91STakashi Iwai {
1162352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1163352f7f91STakashi Iwai 	int i;
1164352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1165352f7f91STakashi Iwai 
1166352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1167352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1168352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1169352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1170352f7f91STakashi Iwai 			continue;
1171352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1172352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1173352f7f91STakashi Iwai 			break;
1174352f7f91STakashi Iwai 		}
1175352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1176352f7f91STakashi Iwai 	}
1177352f7f91STakashi Iwai }
1178352f7f91STakashi Iwai 
1179352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1180352f7f91STakashi Iwai {
1181352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1182352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1183352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1184352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1185352f7f91STakashi Iwai 	int badness;
1186352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1187352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1188352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1189352f7f91STakashi Iwai 
1190352f7f91STakashi Iwai 	fill_all_dac_nids(codec);
1191352f7f91STakashi Iwai 
1192352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1193352f7f91STakashi Iwai 	if (!best_cfg)
1194352f7f91STakashi Iwai 		return -ENOMEM;
1195352f7f91STakashi Iwai 	*best_cfg = *cfg;
1196352f7f91STakashi Iwai 
1197352f7f91STakashi Iwai 	for (;;) {
1198352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1199352f7f91STakashi Iwai 					     fill_mio_first);
1200352f7f91STakashi Iwai 		if (badness < 0) {
1201352f7f91STakashi Iwai 			kfree(best_cfg);
1202352f7f91STakashi Iwai 			return badness;
1203352f7f91STakashi Iwai 		}
1204352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1205352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1206352f7f91STakashi Iwai 			      badness);
1207352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1208352f7f91STakashi Iwai 		if (badness < best_badness) {
1209352f7f91STakashi Iwai 			best_badness = badness;
1210352f7f91STakashi Iwai 			*best_cfg = *cfg;
1211352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1212352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1213352f7f91STakashi Iwai 		}
1214352f7f91STakashi Iwai 		if (!badness)
1215352f7f91STakashi Iwai 			break;
1216352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1217352f7f91STakashi Iwai 		if (!fill_mio_first)
1218352f7f91STakashi Iwai 			continue;
1219352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1220352f7f91STakashi Iwai 		if (!fill_hardwired)
1221352f7f91STakashi Iwai 			continue;
1222352f7f91STakashi Iwai 		if (hp_spk_swapped)
1223352f7f91STakashi Iwai 			break;
1224352f7f91STakashi Iwai 		hp_spk_swapped = true;
1225352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1226352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1227352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1228352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1229352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1230352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1231352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1232352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1233352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1234352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1235352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1236352f7f91STakashi Iwai 			fill_hardwired = true;
1237352f7f91STakashi Iwai 			continue;
1238352f7f91STakashi Iwai 		}
1239352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1240352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1241352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1242352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1243352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1244352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1245352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1246352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1247352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1248352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1249352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1250352f7f91STakashi Iwai 			fill_hardwired = true;
1251352f7f91STakashi Iwai 			continue;
1252352f7f91STakashi Iwai 		}
1253352f7f91STakashi Iwai 		break;
1254352f7f91STakashi Iwai 	}
1255352f7f91STakashi Iwai 
1256352f7f91STakashi Iwai 	if (badness) {
1257352f7f91STakashi Iwai 		*cfg = *best_cfg;
1258352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1259352f7f91STakashi Iwai 	}
1260352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1261352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1262352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1263352f7f91STakashi Iwai 
1264352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1265352f7f91STakashi Iwai 		struct nid_path *path;
1266352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec,
1267352f7f91STakashi Iwai 					    spec->multiout.dac_nids[0],
1268352f7f91STakashi Iwai 					    cfg->line_out_pins[0]);
1269352f7f91STakashi Iwai 		if (path)
1270352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
1271352f7f91STakashi Iwai 	}
1272352f7f91STakashi Iwai 
1273352f7f91STakashi Iwai 	kfree(best_cfg);
1274352f7f91STakashi Iwai 	return 0;
1275352f7f91STakashi Iwai }
1276352f7f91STakashi Iwai 
1277352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1278352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1279352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1280352f7f91STakashi Iwai {
1281352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1282352f7f91STakashi Iwai 	int i, err, noutputs;
1283352f7f91STakashi Iwai 
1284352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1285352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1286352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1287352f7f91STakashi Iwai 
1288352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1289352f7f91STakashi Iwai 		const char *name;
1290352f7f91STakashi Iwai 		int index;
1291352f7f91STakashi Iwai 		hda_nid_t dac, pin;
1292352f7f91STakashi Iwai 		struct nid_path *path;
1293352f7f91STakashi Iwai 
1294352f7f91STakashi Iwai 		dac = spec->multiout.dac_nids[i];
1295352f7f91STakashi Iwai 		if (!dac)
1296352f7f91STakashi Iwai 			continue;
1297352f7f91STakashi Iwai 		if (i >= cfg->line_outs) {
1298352f7f91STakashi Iwai 			pin = spec->multi_io[i - 1].pin;
1299352f7f91STakashi Iwai 			index = 0;
1300352f7f91STakashi Iwai 			name = channel_name[i];
1301352f7f91STakashi Iwai 		} else {
1302352f7f91STakashi Iwai 			pin = cfg->line_out_pins[i];
1303352f7f91STakashi Iwai 			name = get_line_out_pfx(spec, i, true, &index);
1304352f7f91STakashi Iwai 		}
1305352f7f91STakashi Iwai 
1306352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, dac, pin);
1307352f7f91STakashi Iwai 		if (!path)
1308352f7f91STakashi Iwai 			continue;
1309352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1310352f7f91STakashi Iwai 			/* Center/LFE */
1311352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1312352f7f91STakashi Iwai 			if (err < 0)
1313352f7f91STakashi Iwai 				return err;
1314352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1315352f7f91STakashi Iwai 			if (err < 0)
1316352f7f91STakashi Iwai 				return err;
1317352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1318352f7f91STakashi Iwai 			if (err < 0)
1319352f7f91STakashi Iwai 				return err;
1320352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1321352f7f91STakashi Iwai 			if (err < 0)
1322352f7f91STakashi Iwai 				return err;
1323352f7f91STakashi Iwai 		} else {
1324352f7f91STakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1325352f7f91STakashi Iwai 			if (err < 0)
1326352f7f91STakashi Iwai 				return err;
1327352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1328352f7f91STakashi Iwai 			if (err < 0)
1329352f7f91STakashi Iwai 				return err;
1330352f7f91STakashi Iwai 		}
1331352f7f91STakashi Iwai 	}
1332352f7f91STakashi Iwai 	return 0;
1333352f7f91STakashi Iwai }
1334352f7f91STakashi Iwai 
1335352f7f91STakashi Iwai static int create_extra_out(struct hda_codec *codec, hda_nid_t pin,
1336352f7f91STakashi Iwai 			    hda_nid_t dac, const char *pfx, int cidx)
1337352f7f91STakashi Iwai {
1338352f7f91STakashi Iwai 	struct nid_path *path;
1339352f7f91STakashi Iwai 	int err;
1340352f7f91STakashi Iwai 
1341352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, dac, pin);
1342352f7f91STakashi Iwai 	if (!path)
1343352f7f91STakashi Iwai 		return 0;
1344352f7f91STakashi Iwai 	/* bind volume control will be created in the case of dac = 0 */
1345352f7f91STakashi Iwai 	if (dac) {
1346352f7f91STakashi Iwai 		err = add_stereo_vol(codec, pfx, cidx, path);
1347352f7f91STakashi Iwai 		if (err < 0)
1348352f7f91STakashi Iwai 			return err;
1349352f7f91STakashi Iwai 	}
1350352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1351352f7f91STakashi Iwai 	if (err < 0)
1352352f7f91STakashi Iwai 		return err;
1353352f7f91STakashi Iwai 	return 0;
1354352f7f91STakashi Iwai }
1355352f7f91STakashi Iwai 
1356352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1357352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1358352f7f91STakashi Iwai 			     const hda_nid_t *pins, const hda_nid_t *dacs,
1359352f7f91STakashi Iwai 			     const char *pfx)
1360352f7f91STakashi Iwai {
1361352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1362352f7f91STakashi Iwai 	struct hda_bind_ctls *ctl;
1363352f7f91STakashi Iwai 	char name[32];
1364352f7f91STakashi Iwai 	int i, n, err;
1365352f7f91STakashi Iwai 
1366352f7f91STakashi Iwai 	if (!num_pins || !pins[0])
1367352f7f91STakashi Iwai 		return 0;
1368352f7f91STakashi Iwai 
1369352f7f91STakashi Iwai 	if (num_pins == 1) {
1370352f7f91STakashi Iwai 		hda_nid_t dac = *dacs;
1371352f7f91STakashi Iwai 		if (!dac)
1372352f7f91STakashi Iwai 			dac = spec->multiout.dac_nids[0];
1373352f7f91STakashi Iwai 		return create_extra_out(codec, *pins, dac, pfx, 0);
1374352f7f91STakashi Iwai 	}
1375352f7f91STakashi Iwai 
1376352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1377352f7f91STakashi Iwai 		hda_nid_t dac;
1378352f7f91STakashi Iwai 		if (dacs[num_pins - 1])
1379352f7f91STakashi Iwai 			dac = dacs[i]; /* with individual volumes */
1380352f7f91STakashi Iwai 		else
1381352f7f91STakashi Iwai 			dac = 0;
1382352f7f91STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
1383352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac,
1384352f7f91STakashi Iwai 					       "Bass Speaker", 0);
1385352f7f91STakashi Iwai 		} else if (num_pins >= 3) {
1386352f7f91STakashi Iwai 			snprintf(name, sizeof(name), "%s %s",
1387352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1388352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, name, 0);
1389352f7f91STakashi Iwai 		} else {
1390352f7f91STakashi Iwai 			err = create_extra_out(codec, pins[i], dac, pfx, i);
1391352f7f91STakashi Iwai 		}
1392352f7f91STakashi Iwai 		if (err < 0)
1393352f7f91STakashi Iwai 			return err;
1394352f7f91STakashi Iwai 	}
1395352f7f91STakashi Iwai 	if (dacs[num_pins - 1])
1396352f7f91STakashi Iwai 		return 0;
1397352f7f91STakashi Iwai 
1398352f7f91STakashi Iwai 	/* Let's create a bind-controls for volumes */
1399352f7f91STakashi Iwai 	ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
1400352f7f91STakashi Iwai 	if (!ctl)
1401352f7f91STakashi Iwai 		return -ENOMEM;
1402352f7f91STakashi Iwai 	n = 0;
1403352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1404352f7f91STakashi Iwai 		hda_nid_t vol;
1405352f7f91STakashi Iwai 		struct nid_path *path;
1406352f7f91STakashi Iwai 		if (!pins[i] || !dacs[i])
1407352f7f91STakashi Iwai 			continue;
1408352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, dacs[i], pins[i]);
1409352f7f91STakashi Iwai 		if (!path)
1410352f7f91STakashi Iwai 			continue;
1411352f7f91STakashi Iwai 		vol = look_for_out_vol_nid(codec, path);
1412352f7f91STakashi Iwai 		if (vol)
1413352f7f91STakashi Iwai 			ctl->values[n++] =
1414352f7f91STakashi Iwai 				HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
1415352f7f91STakashi Iwai 	}
1416352f7f91STakashi Iwai 	if (n) {
1417352f7f91STakashi Iwai 		snprintf(name, sizeof(name), "%s Playback Volume", pfx);
1418352f7f91STakashi Iwai 		err = add_control(spec, HDA_CTL_BIND_VOL, name, 0, (long)ctl);
1419352f7f91STakashi Iwai 		if (err < 0)
1420352f7f91STakashi Iwai 			return err;
1421352f7f91STakashi Iwai 	}
1422352f7f91STakashi Iwai 	return 0;
1423352f7f91STakashi Iwai }
1424352f7f91STakashi Iwai 
1425352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1426352f7f91STakashi Iwai {
1427352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1428352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1429352f7f91STakashi Iwai 				 spec->autocfg.hp_pins,
1430352f7f91STakashi Iwai 				 spec->multiout.hp_out_nid,
1431352f7f91STakashi Iwai 				 "Headphone");
1432352f7f91STakashi Iwai }
1433352f7f91STakashi Iwai 
1434352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1435352f7f91STakashi Iwai {
1436352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1437352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1438352f7f91STakashi Iwai 				 spec->autocfg.speaker_pins,
1439352f7f91STakashi Iwai 				 spec->multiout.extra_out_nid,
1440352f7f91STakashi Iwai 				 "Speaker");
1441352f7f91STakashi Iwai }
1442352f7f91STakashi Iwai 
1443352f7f91STakashi Iwai /*
1444352f7f91STakashi Iwai  * channel mode enum control
1445352f7f91STakashi Iwai  */
1446352f7f91STakashi Iwai 
1447352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1448352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1449352f7f91STakashi Iwai {
1450352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1451352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1452352f7f91STakashi Iwai 
1453352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1454352f7f91STakashi Iwai 	uinfo->count = 1;
1455352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1456352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1457352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1458352f7f91STakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch",
1459352f7f91STakashi Iwai 		(uinfo->value.enumerated.item + 1) * 2);
1460352f7f91STakashi Iwai 	return 0;
1461352f7f91STakashi Iwai }
1462352f7f91STakashi Iwai 
1463352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1464352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1465352f7f91STakashi Iwai {
1466352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1467352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1468352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
1469352f7f91STakashi Iwai 	return 0;
1470352f7f91STakashi Iwai }
1471352f7f91STakashi Iwai 
1472352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1473352f7f91STakashi Iwai {
1474352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1475352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1476352f7f91STakashi Iwai 	struct nid_path *path;
1477352f7f91STakashi Iwai 
1478352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->multi_io[idx].dac, nid);
1479352f7f91STakashi Iwai 	if (!path)
1480352f7f91STakashi Iwai 		return -EINVAL;
1481352f7f91STakashi Iwai 
1482352f7f91STakashi Iwai 	if (path->active == output)
1483352f7f91STakashi Iwai 		return 0;
1484352f7f91STakashi Iwai 
1485352f7f91STakashi Iwai 	if (output) {
1486352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
1487352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1488352f7f91STakashi Iwai 	} else {
1489352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
1490352f7f91STakashi Iwai 		snd_hda_set_pin_ctl_cache(codec, nid,
1491352f7f91STakashi Iwai 					  spec->multi_io[idx].ctl_in);
1492352f7f91STakashi Iwai 	}
1493352f7f91STakashi Iwai 	return 0;
1494352f7f91STakashi Iwai }
1495352f7f91STakashi Iwai 
1496352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1497352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1498352f7f91STakashi Iwai {
1499352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1500352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1501352f7f91STakashi Iwai 	int i, ch;
1502352f7f91STakashi Iwai 
1503352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1504352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1505352f7f91STakashi Iwai 		return -EINVAL;
1506352f7f91STakashi Iwai 	if (ch == (spec->ext_channel_count - 1) / 2)
1507352f7f91STakashi Iwai 		return 0;
1508352f7f91STakashi Iwai 	spec->ext_channel_count = (ch + 1) * 2;
1509352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1510352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1511352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1512352f7f91STakashi Iwai 					  spec->const_channel_count);
1513352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1514352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1515352f7f91STakashi Iwai 	return 1;
1516352f7f91STakashi Iwai }
1517352f7f91STakashi Iwai 
1518352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1519352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1520352f7f91STakashi Iwai 	.name = "Channel Mode",
1521352f7f91STakashi Iwai 	.info = ch_mode_info,
1522352f7f91STakashi Iwai 	.get = ch_mode_get,
1523352f7f91STakashi Iwai 	.put = ch_mode_put,
1524352f7f91STakashi Iwai };
1525352f7f91STakashi Iwai 
1526352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1527352f7f91STakashi Iwai {
1528352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1529352f7f91STakashi Iwai 
1530352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
153112c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1532352f7f91STakashi Iwai 			return -ENOMEM;
1533352f7f91STakashi Iwai 	}
1534352f7f91STakashi Iwai 	return 0;
1535352f7f91STakashi Iwai }
1536352f7f91STakashi Iwai 
1537352f7f91STakashi Iwai /*
1538352f7f91STakashi Iwai  * shared headphone/mic handling
1539352f7f91STakashi Iwai  */
1540352f7f91STakashi Iwai 
1541352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
1542352f7f91STakashi Iwai 
1543352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
1544352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
1545352f7f91STakashi Iwai {
1546352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1547352f7f91STakashi Iwai 	unsigned int val;
1548352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
1549352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
1550352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
1551352f7f91STakashi Iwai 	 */
1552352f7f91STakashi Iwai 
1553352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
1554352f7f91STakashi Iwai 
1555352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
1556352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
1557352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
1558352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
1559352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
1560352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
1561352f7f91STakashi Iwai 			snd_hda_set_pin_ctl(codec, vref_pin, PIN_IN | (set_as_mic ? vref_val : 0));
1562352f7f91STakashi Iwai 	}
1563352f7f91STakashi Iwai 
1564352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
1565352f7f91STakashi Iwai 	snd_hda_set_pin_ctl(codec, pin, val);
1566352f7f91STakashi Iwai 
1567352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
1568352f7f91STakashi Iwai 	call_update_outputs(codec);
1569352f7f91STakashi Iwai }
1570352f7f91STakashi Iwai 
1571352f7f91STakashi Iwai /* create a shared input with the headphone out */
1572352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
1573352f7f91STakashi Iwai {
1574352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1575352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1576352f7f91STakashi Iwai 	unsigned int defcfg;
1577352f7f91STakashi Iwai 	hda_nid_t nid;
1578352f7f91STakashi Iwai 
1579352f7f91STakashi Iwai 	/* only one internal input pin? */
1580352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
1581352f7f91STakashi Iwai 		return 0;
1582352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
1583352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
1584352f7f91STakashi Iwai 		return 0;
1585352f7f91STakashi Iwai 
1586352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1587352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
1588352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
1589352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
1590352f7f91STakashi Iwai 	else
1591352f7f91STakashi Iwai 		return 0; /* both not available */
1592352f7f91STakashi Iwai 
1593352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
1594352f7f91STakashi Iwai 		return 0; /* no input */
1595352f7f91STakashi Iwai 
1596352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
1597352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
1598352f7f91STakashi Iwai 	cfg->num_inputs = 2;
1599352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
1600352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
1601352f7f91STakashi Iwai 	return 0;
1602352f7f91STakashi Iwai }
1603352f7f91STakashi Iwai 
1604352f7f91STakashi Iwai 
1605352f7f91STakashi Iwai /*
1606352f7f91STakashi Iwai  * Parse input paths
1607352f7f91STakashi Iwai  */
1608352f7f91STakashi Iwai 
1609352f7f91STakashi Iwai #ifdef CONFIG_PM
1610352f7f91STakashi Iwai /* add the powersave loopback-list entry */
1611352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
1612352f7f91STakashi Iwai {
1613352f7f91STakashi Iwai 	struct hda_amp_list *list;
1614352f7f91STakashi Iwai 
1615352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
1616352f7f91STakashi Iwai 		return;
1617352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
1618352f7f91STakashi Iwai 	list->nid = mix;
1619352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
1620352f7f91STakashi Iwai 	list->idx = idx;
1621352f7f91STakashi Iwai 	spec->num_loopbacks++;
1622cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
1623cb53c626STakashi Iwai }
1624cb53c626STakashi Iwai #else
1625352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
1626cb53c626STakashi Iwai #endif
1627cb53c626STakashi Iwai 
1628352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
1629352f7f91STakashi Iwai static int new_analog_input(struct hda_codec *codec, hda_nid_t pin,
1630352f7f91STakashi Iwai 			    const char *ctlname, int ctlidx,
1631352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
16321da177e4SLinus Torvalds {
1633352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1634352f7f91STakashi Iwai 	struct nid_path *path;
1635352f7f91STakashi Iwai 	unsigned int val;
1636352f7f91STakashi Iwai 	int err, idx;
16371da177e4SLinus Torvalds 
1638352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
1639352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
1640352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
1641352f7f91STakashi Iwai 
1642352f7f91STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 2);
1643352f7f91STakashi Iwai 	if (!path)
1644352f7f91STakashi Iwai 		return -EINVAL;
1645352f7f91STakashi Iwai 
1646352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
1647352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
1648352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1649352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
1650d13bd412STakashi Iwai 		if (err < 0)
16511da177e4SLinus Torvalds 			return err;
1652352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
16531da177e4SLinus Torvalds 	}
16541da177e4SLinus Torvalds 
1655352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
1656352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
1657352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
1658d13bd412STakashi Iwai 		if (err < 0)
16591da177e4SLinus Torvalds 			return err;
1660352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
16611da177e4SLinus Torvalds 	}
16621da177e4SLinus Torvalds 
1663352f7f91STakashi Iwai 	path->active = true;
1664352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
1665352f7f91STakashi Iwai 	return 0;
16661da177e4SLinus Torvalds }
16671da177e4SLinus Torvalds 
1668352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
16691da177e4SLinus Torvalds {
1670352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
1671352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
1672352f7f91STakashi Iwai }
1673352f7f91STakashi Iwai 
1674352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
1675352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
1676352f7f91STakashi Iwai {
1677352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1678352f7f91STakashi Iwai 	hda_nid_t nid;
1679352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
1680352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
1681352f7f91STakashi Iwai 	int i, nums = 0;
1682352f7f91STakashi Iwai 
1683352f7f91STakashi Iwai 	nid = codec->start_nid;
1684352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1685352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
1686352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
1687352f7f91STakashi Iwai 
1688352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
1689352f7f91STakashi Iwai 			continue;
1690352f7f91STakashi Iwai 		adc_nids[nums] = nid;
1691352f7f91STakashi Iwai 		if (++nums >= max_nums)
1692352f7f91STakashi Iwai 			break;
1693352f7f91STakashi Iwai 	}
1694352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
1695352f7f91STakashi Iwai 	return nums;
1696352f7f91STakashi Iwai }
1697352f7f91STakashi Iwai 
1698352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
1699352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
1700352f7f91STakashi Iwai  */
1701352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
1702352f7f91STakashi Iwai {
1703352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1704352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
1705352f7f91STakashi Iwai 	hda_nid_t adc_nids[ARRAY_SIZE(spec->adc_nids)];
1706352f7f91STakashi Iwai 	int i, n, nums;
1707352f7f91STakashi Iwai 	hda_nid_t pin, adc;
1708352f7f91STakashi Iwai 
1709352f7f91STakashi Iwai  again:
1710352f7f91STakashi Iwai 	nums = 0;
1711352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
1712352f7f91STakashi Iwai 		adc = spec->adc_nids[n];
1713352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1714352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1715352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
1716352f7f91STakashi Iwai 				break;
1717352f7f91STakashi Iwai 		}
1718352f7f91STakashi Iwai 		if (i >= imux->num_items)
1719352f7f91STakashi Iwai 			adc_nids[nums++] = adc;
1720352f7f91STakashi Iwai 	}
1721352f7f91STakashi Iwai 
1722352f7f91STakashi Iwai 	if (!nums) {
1723352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
1724352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
1725352f7f91STakashi Iwai 			imux->num_items = 1;
1726352f7f91STakashi Iwai 			goto again;
1727352f7f91STakashi Iwai 		}
1728352f7f91STakashi Iwai 
1729352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
1730352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
1731352f7f91STakashi Iwai 			pin = spec->imux_pins[i];
1732352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
1733352f7f91STakashi Iwai 				adc = spec->adc_nids[n];
1734352f7f91STakashi Iwai 				if (is_reachable_path(codec, pin, adc)) {
1735352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
1736352f7f91STakashi Iwai 					break;
1737352f7f91STakashi Iwai 				}
1738352f7f91STakashi Iwai 			}
1739352f7f91STakashi Iwai 		}
1740352f7f91STakashi Iwai 
1741352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
1742352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
1743352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
1744352f7f91STakashi Iwai 		memcpy(spec->adc_nids, adc_nids, nums * sizeof(hda_nid_t));
1745352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
1746352f7f91STakashi Iwai 	}
1747352f7f91STakashi Iwai 
1748352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
1749352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
1750352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
1751352f7f91STakashi Iwai 	}
1752352f7f91STakashi Iwai 
1753352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
1754352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
1755352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
1756352f7f91STakashi Iwai 
17571da177e4SLinus Torvalds 	return 0;
17581da177e4SLinus Torvalds }
17591da177e4SLinus Torvalds 
17601da177e4SLinus Torvalds /*
1761352f7f91STakashi Iwai  * create playback/capture controls for input pins
17621da177e4SLinus Torvalds  */
1763352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
1764a7da6ce5STakashi Iwai {
1765352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1766352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
1767352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
1768352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
1769352f7f91STakashi Iwai 	int num_adcs;
1770352f7f91STakashi Iwai 	int i, c, err, type_idx = 0;
1771352f7f91STakashi Iwai 	const char *prev_label = NULL;
1772a7da6ce5STakashi Iwai 
1773352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
1774352f7f91STakashi Iwai 	if (num_adcs < 0)
1775352f7f91STakashi Iwai 		return 0;
1776352f7f91STakashi Iwai 
1777352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
1778352f7f91STakashi Iwai 		hda_nid_t pin;
1779352f7f91STakashi Iwai 		const char *label;
1780352f7f91STakashi Iwai 		bool imux_added;
1781352f7f91STakashi Iwai 
1782352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
1783352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
1784352f7f91STakashi Iwai 			continue;
1785352f7f91STakashi Iwai 
1786352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
1787352f7f91STakashi Iwai 		if (spec->shared_mic_hp && !strcmp(label, "Misc"))
1788352f7f91STakashi Iwai 			label = "Headphone Mic";
1789352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
1790352f7f91STakashi Iwai 			type_idx++;
1791352f7f91STakashi Iwai 		else
1792352f7f91STakashi Iwai 			type_idx = 0;
1793352f7f91STakashi Iwai 		prev_label = label;
1794352f7f91STakashi Iwai 
1795352f7f91STakashi Iwai 		if (mixer) {
1796352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
1797352f7f91STakashi Iwai 				err = new_analog_input(codec, pin,
1798352f7f91STakashi Iwai 						       label, type_idx, mixer);
1799a7da6ce5STakashi Iwai 				if (err < 0)
1800a7da6ce5STakashi Iwai 					return err;
1801a7da6ce5STakashi Iwai 			}
1802352f7f91STakashi Iwai 		}
1803352f7f91STakashi Iwai 
1804352f7f91STakashi Iwai 		imux_added = false;
1805352f7f91STakashi Iwai 		for (c = 0; c < num_adcs; c++) {
1806352f7f91STakashi Iwai 			struct nid_path *path;
1807352f7f91STakashi Iwai 			hda_nid_t adc = spec->adc_nids[c];
1808352f7f91STakashi Iwai 
1809352f7f91STakashi Iwai 			if (!is_reachable_path(codec, pin, adc))
1810352f7f91STakashi Iwai 				continue;
1811352f7f91STakashi Iwai 			path = snd_array_new(&spec->paths);
1812352f7f91STakashi Iwai 			if (!path)
1813352f7f91STakashi Iwai 				return -ENOMEM;
1814352f7f91STakashi Iwai 			memset(path, 0, sizeof(*path));
1815352f7f91STakashi Iwai 			if (!snd_hda_parse_nid_path(codec, pin, adc, 2, path)) {
1816352f7f91STakashi Iwai 				snd_printd(KERN_ERR
1817352f7f91STakashi Iwai 					   "invalid input path 0x%x -> 0x%x\n",
1818352f7f91STakashi Iwai 					   pin, adc);
1819352f7f91STakashi Iwai 				spec->paths.used--;
1820352f7f91STakashi Iwai 				continue;
1821352f7f91STakashi Iwai 			}
1822352f7f91STakashi Iwai 
1823352f7f91STakashi Iwai 			if (!imux_added) {
1824352f7f91STakashi Iwai 				spec->imux_pins[imux->num_items] = pin;
1825352f7f91STakashi Iwai 				snd_hda_add_imux_item(imux, label,
1826352f7f91STakashi Iwai 						      imux->num_items, NULL);
1827352f7f91STakashi Iwai 				imux_added = true;
1828352f7f91STakashi Iwai 			}
1829352f7f91STakashi Iwai 		}
1830352f7f91STakashi Iwai 	}
1831352f7f91STakashi Iwai 
1832a7da6ce5STakashi Iwai 	return 0;
1833a7da6ce5STakashi Iwai }
1834a7da6ce5STakashi Iwai 
18351da177e4SLinus Torvalds 
1836352f7f91STakashi Iwai /*
1837352f7f91STakashi Iwai  * input source mux
1838352f7f91STakashi Iwai  */
1839352f7f91STakashi Iwai 
1840352f7f91STakashi Iwai /* get the ADC NID corresponding to the given index */
1841352f7f91STakashi Iwai static hda_nid_t get_adc_nid(struct hda_codec *codec, int adc_idx, int imux_idx)
1842352f7f91STakashi Iwai {
1843352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1844352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
1845352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
1846352f7f91STakashi Iwai 	return spec->adc_nids[adc_idx];
184797ec558aSTakashi Iwai }
1848352f7f91STakashi Iwai 
1849352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
1850352f7f91STakashi Iwai 		      unsigned int idx);
1851352f7f91STakashi Iwai 
1852352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
1853352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
1854352f7f91STakashi Iwai {
1855352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1856352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1857352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
1858352f7f91STakashi Iwai }
1859352f7f91STakashi Iwai 
1860352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
1861352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
1862352f7f91STakashi Iwai {
1863352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1864352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1865352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1866352f7f91STakashi Iwai 
1867352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
18681da177e4SLinus Torvalds 	return 0;
18691da177e4SLinus Torvalds }
18701da177e4SLinus Torvalds 
1871352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
1872352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
18731da177e4SLinus Torvalds {
1874352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1875352f7f91STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1876352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
1877352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
1878352f7f91STakashi Iwai }
1879352f7f91STakashi Iwai 
1880352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
18811da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1882352f7f91STakashi Iwai 	.name = "Input Source",
1883352f7f91STakashi Iwai 	.info = mux_enum_info,
1884352f7f91STakashi Iwai 	.get = mux_enum_get,
1885352f7f91STakashi Iwai 	.put = mux_enum_put,
18861da177e4SLinus Torvalds };
1887071c73adSTakashi Iwai 
188847d46abbSTakashi Iwai /*
188947d46abbSTakashi Iwai  * capture volume and capture switch ctls
189047d46abbSTakashi Iwai  */
189147d46abbSTakashi Iwai 
1892352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
1893352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
1894071c73adSTakashi Iwai 
189547d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
1896352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
1897352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
1898352f7f91STakashi Iwai 			  put_call_t func, int type)
1899352f7f91STakashi Iwai {
1900352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1901352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1902352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
1903352f7f91STakashi Iwai 	struct nid_path *path;
1904352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
1905071c73adSTakashi Iwai 
1906352f7f91STakashi Iwai 	imux = &spec->input_mux;
1907352f7f91STakashi Iwai 	adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1908352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
190947d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
191047d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
191147d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
191247d46abbSTakashi Iwai 	 */
1913352f7f91STakashi Iwai 	codec->cached_write = 1;
1914352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
1915352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
1916352f7f91STakashi Iwai 					    get_adc_nid(codec, adc_idx, i));
1917352f7f91STakashi Iwai 		if (!path->ctls[type])
1918352f7f91STakashi Iwai 			continue;
1919352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
1920352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
1921352f7f91STakashi Iwai 		if (err < 0)
1922352f7f91STakashi Iwai 			goto error;
1923352f7f91STakashi Iwai 	}
1924352f7f91STakashi Iwai  error:
1925352f7f91STakashi Iwai 	codec->cached_write = 0;
1926352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
192747d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
1928352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
1929352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
1930352f7f91STakashi Iwai 	return err;
1931352f7f91STakashi Iwai }
1932352f7f91STakashi Iwai 
1933352f7f91STakashi Iwai /* capture volume ctl callbacks */
1934352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
1935352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
1936352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
1937352f7f91STakashi Iwai 
1938352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
1939352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1940352f7f91STakashi Iwai {
1941352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
1942352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
1943352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
1944352f7f91STakashi Iwai }
1945352f7f91STakashi Iwai 
1946352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
1947352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1948352f7f91STakashi Iwai 	.name = "Capture Volume",
1949352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1950352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
1951352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
1952352f7f91STakashi Iwai 	.info = cap_vol_info,
1953352f7f91STakashi Iwai 	.get = cap_vol_get,
1954352f7f91STakashi Iwai 	.put = cap_vol_put,
1955352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
1956352f7f91STakashi Iwai };
1957352f7f91STakashi Iwai 
1958352f7f91STakashi Iwai /* capture switch ctl callbacks */
1959352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
1960352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
1961352f7f91STakashi Iwai 
1962352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
1963352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
1964352f7f91STakashi Iwai {
1965352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
1966352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
1967352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
1968352f7f91STakashi Iwai }
1969352f7f91STakashi Iwai 
1970352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
1971352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1972352f7f91STakashi Iwai 	.name = "Capture Switch",
1973352f7f91STakashi Iwai 	.info = cap_sw_info,
1974352f7f91STakashi Iwai 	.get = cap_sw_get,
1975352f7f91STakashi Iwai 	.put = cap_sw_put,
1976352f7f91STakashi Iwai };
1977352f7f91STakashi Iwai 
1978352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
1979352f7f91STakashi Iwai {
1980352f7f91STakashi Iwai 	hda_nid_t nid;
1981352f7f91STakashi Iwai 	int i, depth;
1982352f7f91STakashi Iwai 
1983352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
1984352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
1985352f7f91STakashi Iwai 		if (depth >= path->depth)
1986352f7f91STakashi Iwai 			return -EINVAL;
1987352f7f91STakashi Iwai 		i = path->depth - depth - 1;
1988352f7f91STakashi Iwai 		nid = path->path[i];
1989352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
1990352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
1991352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
1992352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1993352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
1994352f7f91STakashi Iwai 				int idx = path->idx[i];
1995352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
1996352f7f91STakashi Iwai 					idx = 0;
1997352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
1998352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
1999352f7f91STakashi Iwai 			}
2000352f7f91STakashi Iwai 		}
2001352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2002352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2003352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2004352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2005352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2006352f7f91STakashi Iwai 				int idx = path->idx[i];
2007352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2008352f7f91STakashi Iwai 					idx = 0;
2009352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2010352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2011352f7f91STakashi Iwai 			}
2012352f7f91STakashi Iwai 		}
2013352f7f91STakashi Iwai 	}
2014352f7f91STakashi Iwai 	return 0;
2015352f7f91STakashi Iwai }
2016352f7f91STakashi Iwai 
2017352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2018352f7f91STakashi Iwai {
2019352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2020352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2021352f7f91STakashi Iwai 	unsigned int val;
2022352f7f91STakashi Iwai 	int i;
2023352f7f91STakashi Iwai 
2024352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2025352f7f91STakashi Iwai 		return false;
2026352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2027352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2028352f7f91STakashi Iwai 			continue;
2029352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2030352f7f91STakashi Iwai 			return false;
2031352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2032352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2033352f7f91STakashi Iwai 	}
2034352f7f91STakashi Iwai 	return false;
2035352f7f91STakashi Iwai }
2036352f7f91STakashi Iwai 
2037352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2038352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2039352f7f91STakashi Iwai 			      bool inv_dmic)
2040352f7f91STakashi Iwai {
2041352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2042352f7f91STakashi Iwai 	char tmpname[44];
2043352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2044352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2045352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2046352f7f91STakashi Iwai 	int err;
2047352f7f91STakashi Iwai 
2048352f7f91STakashi Iwai 	if (!ctl)
2049352f7f91STakashi Iwai 		return 0;
2050352f7f91STakashi Iwai 
2051352f7f91STakashi Iwai 	if (label)
2052352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2053352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2054352f7f91STakashi Iwai 	else
2055352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2056352f7f91STakashi Iwai 			 "Capture %s", sfx);
2057352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2058352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2059352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2060352f7f91STakashi Iwai 		return err;
2061352f7f91STakashi Iwai 
2062352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2063352f7f91STakashi Iwai 	if (label)
2064352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2065352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2066352f7f91STakashi Iwai 	else
2067352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2068352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2069352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2070352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2071352f7f91STakashi Iwai }
2072352f7f91STakashi Iwai 
2073352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2074352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2075352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2076352f7f91STakashi Iwai 				     bool inv_dmic)
2077352f7f91STakashi Iwai {
2078352f7f91STakashi Iwai 	int err;
2079352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2080352f7f91STakashi Iwai 	if (err < 0)
2081352f7f91STakashi Iwai 		return err;
2082352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2083071c73adSTakashi Iwai 	if (err < 0)
2084071c73adSTakashi Iwai 		return err;
2085071c73adSTakashi Iwai 	return 0;
20861da177e4SLinus Torvalds }
2087071c73adSTakashi Iwai 
2088352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2089352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2090352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2091352f7f91STakashi Iwai {
2092352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2093352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2094352f7f91STakashi Iwai 
2095352f7f91STakashi Iwai 	if (vol_ctl) {
209612c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2097352f7f91STakashi Iwai 		if (!knew)
2098352f7f91STakashi Iwai 			return -ENOMEM;
2099352f7f91STakashi Iwai 		knew->index = idx;
2100352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2101352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2102352f7f91STakashi Iwai 	}
2103352f7f91STakashi Iwai 	if (sw_ctl) {
210412c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2105352f7f91STakashi Iwai 		if (!knew)
2106352f7f91STakashi Iwai 			return -ENOMEM;
2107352f7f91STakashi Iwai 		knew->index = idx;
2108352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2109352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2110352f7f91STakashi Iwai 	}
2111352f7f91STakashi Iwai 	return 0;
2112352f7f91STakashi Iwai }
2113352f7f91STakashi Iwai 
2114352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2115352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2116352f7f91STakashi Iwai {
2117352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2118352f7f91STakashi Iwai 	struct nid_path *path;
2119352f7f91STakashi Iwai 	unsigned int ctl;
2120352f7f91STakashi Iwai 	int i;
2121352f7f91STakashi Iwai 
2122352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2123352f7f91STakashi Iwai 				    get_adc_nid(codec, 0, idx));
2124352f7f91STakashi Iwai 	if (!path)
2125352f7f91STakashi Iwai 		return 0;
2126352f7f91STakashi Iwai 	ctl = path->ctls[type];
2127352f7f91STakashi Iwai 	if (!ctl)
2128352f7f91STakashi Iwai 		return 0;
2129352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2130352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2131352f7f91STakashi Iwai 					    get_adc_nid(codec, 0, i));
2132352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2133352f7f91STakashi Iwai 			return 0;
2134352f7f91STakashi Iwai 	}
2135352f7f91STakashi Iwai 	return ctl;
2136352f7f91STakashi Iwai }
2137352f7f91STakashi Iwai 
2138352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2139352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2140352f7f91STakashi Iwai {
2141352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2142352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2143352f7f91STakashi Iwai 	int i, err, type, type_idx = 0;
2144352f7f91STakashi Iwai 	const char *prev_label = NULL;
2145352f7f91STakashi Iwai 
2146352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2147352f7f91STakashi Iwai 		const char *label;
2148352f7f91STakashi Iwai 		bool inv_dmic;
2149352f7f91STakashi Iwai 		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
2150352f7f91STakashi Iwai 		if (prev_label && !strcmp(label, prev_label))
2151352f7f91STakashi Iwai 			type_idx++;
2152352f7f91STakashi Iwai 		else
2153352f7f91STakashi Iwai 			type_idx = 0;
2154352f7f91STakashi Iwai 		prev_label = label;
2155352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2156352f7f91STakashi Iwai 
2157352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2158352f7f91STakashi Iwai 			err = add_single_cap_ctl(codec, label, type_idx, type,
2159352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2160352f7f91STakashi Iwai 						 inv_dmic);
2161d13bd412STakashi Iwai 			if (err < 0)
2162071c73adSTakashi Iwai 				return err;
2163352f7f91STakashi Iwai 		}
2164352f7f91STakashi Iwai 	}
2165071c73adSTakashi Iwai 	return 0;
2166352f7f91STakashi Iwai }
2167071c73adSTakashi Iwai 
2168352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2169352f7f91STakashi Iwai {
2170352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2171352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2172352f7f91STakashi Iwai 	int i, n, nums, err;
2173352f7f91STakashi Iwai 
2174352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2175352f7f91STakashi Iwai 		nums = 1;
2176352f7f91STakashi Iwai 	else
2177352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2178352f7f91STakashi Iwai 
2179352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
2180352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
2181624d914dSTakashi Iwai 		const char *name;
2182624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
2183624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
2184352f7f91STakashi Iwai 		if (!knew)
2185352f7f91STakashi Iwai 			return -ENOMEM;
2186352f7f91STakashi Iwai 		knew->count = nums;
2187352f7f91STakashi Iwai 	}
2188352f7f91STakashi Iwai 
2189352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
2190352f7f91STakashi Iwai 		bool multi = false;
2191352f7f91STakashi Iwai 		bool inv_dmic = false;
2192352f7f91STakashi Iwai 		int vol, sw;
2193352f7f91STakashi Iwai 
2194352f7f91STakashi Iwai 		vol = sw = 0;
2195352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2196352f7f91STakashi Iwai 			struct nid_path *path;
2197352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
2198352f7f91STakashi Iwai 						    get_adc_nid(codec, n, i));
2199352f7f91STakashi Iwai 			if (!path)
2200352f7f91STakashi Iwai 				continue;
2201352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
2202352f7f91STakashi Iwai 			if (!vol)
2203352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
2204352f7f91STakashi Iwai 			else if (vol != path->ctls[NID_PATH_VOL_CTL])
2205352f7f91STakashi Iwai 				multi = true;
2206352f7f91STakashi Iwai 			if (!sw)
2207352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
2208352f7f91STakashi Iwai 			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
2209352f7f91STakashi Iwai 				multi = true;
2210352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
2211352f7f91STakashi Iwai 				inv_dmic = true;
2212352f7f91STakashi Iwai 		}
2213352f7f91STakashi Iwai 
2214352f7f91STakashi Iwai 		if (!multi)
2215352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
2216352f7f91STakashi Iwai 							inv_dmic);
2217352f7f91STakashi Iwai 		else if (!spec->multi_cap_vol)
2218352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
2219352f7f91STakashi Iwai 		else
2220352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
2221d13bd412STakashi Iwai 		if (err < 0)
2222071c73adSTakashi Iwai 			return err;
2223071c73adSTakashi Iwai 	}
2224071c73adSTakashi Iwai 
22251da177e4SLinus Torvalds 	return 0;
22261da177e4SLinus Torvalds }
22271da177e4SLinus Torvalds 
2228352f7f91STakashi Iwai /*
2229352f7f91STakashi Iwai  * add mic boosts if needed
2230352f7f91STakashi Iwai  */
2231352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
2232352f7f91STakashi Iwai {
2233352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2234352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2235352f7f91STakashi Iwai 	int i, err;
2236352f7f91STakashi Iwai 	int type_idx = 0;
2237352f7f91STakashi Iwai 	hda_nid_t nid;
2238352f7f91STakashi Iwai 	const char *prev_label = NULL;
2239352f7f91STakashi Iwai 
2240352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2241352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
2242352f7f91STakashi Iwai 			break;
2243352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
2244352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
2245352f7f91STakashi Iwai 			const char *label;
2246352f7f91STakashi Iwai 			char boost_label[32];
2247352f7f91STakashi Iwai 			struct nid_path *path;
2248352f7f91STakashi Iwai 			unsigned int val;
2249352f7f91STakashi Iwai 
2250352f7f91STakashi Iwai 			label = hda_get_autocfg_input_label(codec, cfg, i);
2251352f7f91STakashi Iwai 			if (spec->shared_mic_hp && !strcmp(label, "Misc"))
2252352f7f91STakashi Iwai 				label = "Headphone Mic";
2253352f7f91STakashi Iwai 			if (prev_label && !strcmp(label, prev_label))
2254352f7f91STakashi Iwai 				type_idx++;
2255352f7f91STakashi Iwai 			else
2256352f7f91STakashi Iwai 				type_idx = 0;
2257352f7f91STakashi Iwai 			prev_label = label;
2258352f7f91STakashi Iwai 
2259352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
2260352f7f91STakashi Iwai 				 "%s Boost Volume", label);
2261352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
2262352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
2263352f7f91STakashi Iwai 					  boost_label, type_idx, val);
2264352f7f91STakashi Iwai 			if (err < 0)
2265352f7f91STakashi Iwai 				return err;
2266352f7f91STakashi Iwai 
2267352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
2268352f7f91STakashi Iwai 			if (path)
2269352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
2270352f7f91STakashi Iwai 		}
2271352f7f91STakashi Iwai 	}
2272352f7f91STakashi Iwai 	return 0;
2273352f7f91STakashi Iwai }
2274352f7f91STakashi Iwai 
2275352f7f91STakashi Iwai /*
2276352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
2277352f7f91STakashi Iwai  */
2278352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
2279352f7f91STakashi Iwai {
2280352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2281352f7f91STakashi Iwai 	int i, nums;
2282352f7f91STakashi Iwai 	hda_nid_t dig_nid;
2283352f7f91STakashi Iwai 
2284352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
2285352f7f91STakashi Iwai 	nums = 0;
2286352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
2287352f7f91STakashi Iwai 		hda_nid_t pin = spec->autocfg.dig_out_pins[i];
2288352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
2289352f7f91STakashi Iwai 		if (!dig_nid)
2290352f7f91STakashi Iwai 			continue;
2291352f7f91STakashi Iwai 		if (!snd_hda_add_new_path(codec, dig_nid, pin, 2))
2292352f7f91STakashi Iwai 			continue;
2293352f7f91STakashi Iwai 		if (!nums) {
2294352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
2295352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
2296352f7f91STakashi Iwai 		} else {
2297352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
2298352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
2299352f7f91STakashi Iwai 			break;
2300352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
2301352f7f91STakashi Iwai 		}
2302352f7f91STakashi Iwai 		nums++;
2303352f7f91STakashi Iwai 	}
2304352f7f91STakashi Iwai 
2305352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
2306352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
2307352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
2308352f7f91STakashi Iwai 			struct nid_path *path;
2309352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
2310352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
2311352f7f91STakashi Iwai 				continue;
2312352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
2313352f7f91STakashi Iwai 				continue;
2314352f7f91STakashi Iwai 			path = snd_hda_add_new_path(codec,
2315352f7f91STakashi Iwai 						    spec->autocfg.dig_in_pin,
2316352f7f91STakashi Iwai 						    dig_nid, 2);
2317352f7f91STakashi Iwai 			if (path) {
2318352f7f91STakashi Iwai 				path->active = true;
2319352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
2320352f7f91STakashi Iwai 				break;
2321352f7f91STakashi Iwai 			}
2322352f7f91STakashi Iwai 		}
2323352f7f91STakashi Iwai 	}
2324352f7f91STakashi Iwai }
2325352f7f91STakashi Iwai 
23261da177e4SLinus Torvalds 
23271da177e4SLinus Torvalds /*
2328352f7f91STakashi Iwai  * input MUX handling
23291da177e4SLinus Torvalds  */
23301da177e4SLinus Torvalds 
2331352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
2332352f7f91STakashi Iwai 
2333352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
2334352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2335352f7f91STakashi Iwai 		      unsigned int idx)
2336352f7f91STakashi Iwai {
2337352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2338352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2339352f7f91STakashi Iwai 	struct nid_path *path;
2340352f7f91STakashi Iwai 
2341352f7f91STakashi Iwai 	imux = &spec->input_mux;
2342352f7f91STakashi Iwai 	if (!imux->num_items)
23431da177e4SLinus Torvalds 		return 0;
23441da177e4SLinus Torvalds 
2345352f7f91STakashi Iwai 	if (idx >= imux->num_items)
2346352f7f91STakashi Iwai 		idx = imux->num_items - 1;
2347352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
2348352f7f91STakashi Iwai 		return 0;
2349352f7f91STakashi Iwai 
2350352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec,
2351352f7f91STakashi Iwai 				    spec->imux_pins[spec->cur_mux[adc_idx]],
2352352f7f91STakashi Iwai 				    spec->adc_nids[adc_idx]);
2353352f7f91STakashi Iwai 	if (!path)
2354352f7f91STakashi Iwai 		return 0;
2355352f7f91STakashi Iwai 	if (path->active)
2356352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
2357352f7f91STakashi Iwai 
2358352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
2359352f7f91STakashi Iwai 
2360352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
2361352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
2362352f7f91STakashi Iwai 
2363352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2364352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
2365352f7f91STakashi Iwai 
2366352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, spec->imux_pins[idx],
2367352f7f91STakashi Iwai 				    get_adc_nid(codec, adc_idx, idx));
2368352f7f91STakashi Iwai 	if (!path)
2369352f7f91STakashi Iwai 		return 0;
2370352f7f91STakashi Iwai 	if (path->active)
2371352f7f91STakashi Iwai 		return 0;
2372352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
2373352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
2374352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
23751da177e4SLinus Torvalds 	return 1;
23761da177e4SLinus Torvalds }
23771da177e4SLinus Torvalds 
23781da177e4SLinus Torvalds 
23791da177e4SLinus Torvalds /*
2380352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
23811da177e4SLinus Torvalds  */
2382352f7f91STakashi Iwai 
2383352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
2384352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
23851da177e4SLinus Torvalds {
2386352f7f91STakashi Iwai 	int i, present = 0;
23871da177e4SLinus Torvalds 
2388352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2389352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2390352f7f91STakashi Iwai 		if (!nid)
2391352f7f91STakashi Iwai 			break;
2392352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
23931da177e4SLinus Torvalds 	}
2394352f7f91STakashi Iwai 	return present;
23951da177e4SLinus Torvalds }
23961da177e4SLinus Torvalds 
2397352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
2398352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
2399352f7f91STakashi Iwai 			bool mute, bool hp_out)
24001da177e4SLinus Torvalds {
2401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2402352f7f91STakashi Iwai 	unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
2403352f7f91STakashi Iwai 	int i;
24041da177e4SLinus Torvalds 
2405352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2406352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
2407352f7f91STakashi Iwai 		unsigned int val;
2408352f7f91STakashi Iwai 		if (!nid)
2409352f7f91STakashi Iwai 			break;
2410352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
2411352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
2412352f7f91STakashi Iwai 		 */
2413352f7f91STakashi Iwai 		if (spec->keep_vref_in_automute) {
2414352f7f91STakashi Iwai 			val = snd_hda_codec_read(codec, nid, 0,
2415352f7f91STakashi Iwai 					AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
2416352f7f91STakashi Iwai 			val &= ~PIN_HP;
2417352f7f91STakashi Iwai 		} else
2418352f7f91STakashi Iwai 			val = 0;
2419352f7f91STakashi Iwai 		val |= pin_bits;
2420352f7f91STakashi Iwai 		snd_hda_set_pin_ctl(codec, nid, val);
2421352f7f91STakashi Iwai 	}
2422352f7f91STakashi Iwai }
24231da177e4SLinus Torvalds 
2424352f7f91STakashi Iwai /* Toggle outputs muting */
24255d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
2426352f7f91STakashi Iwai {
2427352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2428352f7f91STakashi Iwai 	int on;
2429352f7f91STakashi Iwai 
2430352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
2431352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
2432352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
2433352f7f91STakashi Iwai 	 */
2434352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
2435352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2436352f7f91STakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute, true);
2437352f7f91STakashi Iwai 
2438352f7f91STakashi Iwai 	if (!spec->automute_speaker)
2439352f7f91STakashi Iwai 		on = 0;
2440352f7f91STakashi Iwai 	else
2441352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
2442352f7f91STakashi Iwai 	on |= spec->master_mute;
2443352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
2444352f7f91STakashi Iwai 		    spec->autocfg.speaker_pins, on, false);
2445352f7f91STakashi Iwai 
2446352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
2447352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
2448352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
2449352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
2450352f7f91STakashi Iwai 		return;
2451352f7f91STakashi Iwai 	if (!spec->automute_lo)
2452352f7f91STakashi Iwai 		on = 0;
2453352f7f91STakashi Iwai 	else
2454352f7f91STakashi Iwai 		on = spec->hp_jack_present;
2455352f7f91STakashi Iwai 	on |= spec->master_mute;
2456352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2457352f7f91STakashi Iwai 		    spec->autocfg.line_out_pins, on, false);
2458352f7f91STakashi Iwai }
24595d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
2460352f7f91STakashi Iwai 
2461352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
2462352f7f91STakashi Iwai {
2463352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2464352f7f91STakashi Iwai 	if (spec->automute_hook)
2465352f7f91STakashi Iwai 		spec->automute_hook(codec);
2466352f7f91STakashi Iwai 	else
24675d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
2468352f7f91STakashi Iwai }
2469352f7f91STakashi Iwai 
2470352f7f91STakashi Iwai /* standard HP-automute helper */
24715d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2472352f7f91STakashi Iwai {
2473352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2474352f7f91STakashi Iwai 
2475352f7f91STakashi Iwai 	spec->hp_jack_present =
2476352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
2477352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
2478352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
2479352f7f91STakashi Iwai 		return;
2480352f7f91STakashi Iwai 	call_update_outputs(codec);
2481352f7f91STakashi Iwai }
24825d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
2483352f7f91STakashi Iwai 
2484352f7f91STakashi Iwai /* standard line-out-automute helper */
24855d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
2486352f7f91STakashi Iwai {
2487352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2488352f7f91STakashi Iwai 
2489352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
2490352f7f91STakashi Iwai 		return;
2491352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
2492352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
2493352f7f91STakashi Iwai 		return;
2494352f7f91STakashi Iwai 
2495352f7f91STakashi Iwai 	spec->line_jack_present =
2496352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
2497352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
2498352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
2499352f7f91STakashi Iwai 		return;
2500352f7f91STakashi Iwai 	call_update_outputs(codec);
2501352f7f91STakashi Iwai }
25025d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
2503352f7f91STakashi Iwai 
2504352f7f91STakashi Iwai /* standard mic auto-switch helper */
25055d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
2506352f7f91STakashi Iwai {
2507352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2508352f7f91STakashi Iwai 	int i;
2509352f7f91STakashi Iwai 
2510352f7f91STakashi Iwai 	if (!spec->auto_mic)
2511352f7f91STakashi Iwai 		return;
2512352f7f91STakashi Iwai 
2513352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
2514352f7f91STakashi Iwai 		if (snd_hda_jack_detect(codec, spec->am_entry[i].pin)) {
2515352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
2516352f7f91STakashi Iwai 			return;
2517352f7f91STakashi Iwai 		}
2518352f7f91STakashi Iwai 	}
2519352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
25201da177e4SLinus Torvalds }
25215d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
25221da177e4SLinus Torvalds 
25231da177e4SLinus Torvalds /*
2524352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
25251da177e4SLinus Torvalds  */
2526352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
2527352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2528352f7f91STakashi Iwai {
2529352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2530352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2531352f7f91STakashi Iwai 	static const char * const texts3[] = {
2532352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
25331da177e4SLinus Torvalds 	};
25341da177e4SLinus Torvalds 
2535352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
2536352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
2537352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
2538352f7f91STakashi Iwai }
2539352f7f91STakashi Iwai 
2540352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
2541352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2542352f7f91STakashi Iwai {
2543352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2544352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2545352f7f91STakashi Iwai 	unsigned int val = 0;
2546352f7f91STakashi Iwai 	if (spec->automute_speaker)
2547352f7f91STakashi Iwai 		val++;
2548352f7f91STakashi Iwai 	if (spec->automute_lo)
2549352f7f91STakashi Iwai 		val++;
2550352f7f91STakashi Iwai 
2551352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
2552352f7f91STakashi Iwai 	return 0;
2553352f7f91STakashi Iwai }
2554352f7f91STakashi Iwai 
2555352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
2556352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2557352f7f91STakashi Iwai {
2558352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2559352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2560352f7f91STakashi Iwai 
2561352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
2562352f7f91STakashi Iwai 	case 0:
2563352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
2564352f7f91STakashi Iwai 			return 0;
2565352f7f91STakashi Iwai 		spec->automute_speaker = 0;
2566352f7f91STakashi Iwai 		spec->automute_lo = 0;
2567352f7f91STakashi Iwai 		break;
2568352f7f91STakashi Iwai 	case 1:
2569352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
2570352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
2571352f7f91STakashi Iwai 				return 0;
2572352f7f91STakashi Iwai 			spec->automute_speaker = 1;
2573352f7f91STakashi Iwai 			spec->automute_lo = 0;
2574352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
2575352f7f91STakashi Iwai 			if (spec->automute_lo)
2576352f7f91STakashi Iwai 				return 0;
2577352f7f91STakashi Iwai 			spec->automute_lo = 1;
2578352f7f91STakashi Iwai 		} else
2579352f7f91STakashi Iwai 			return -EINVAL;
2580352f7f91STakashi Iwai 		break;
2581352f7f91STakashi Iwai 	case 2:
2582352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
2583352f7f91STakashi Iwai 			return -EINVAL;
2584352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
2585352f7f91STakashi Iwai 			return 0;
2586352f7f91STakashi Iwai 		spec->automute_speaker = 1;
2587352f7f91STakashi Iwai 		spec->automute_lo = 1;
2588352f7f91STakashi Iwai 		break;
2589352f7f91STakashi Iwai 	default:
2590352f7f91STakashi Iwai 		return -EINVAL;
2591352f7f91STakashi Iwai 	}
2592352f7f91STakashi Iwai 	call_update_outputs(codec);
2593352f7f91STakashi Iwai 	return 1;
2594352f7f91STakashi Iwai }
2595352f7f91STakashi Iwai 
2596352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
2597352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2598352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
2599352f7f91STakashi Iwai 	.info = automute_mode_info,
2600352f7f91STakashi Iwai 	.get = automute_mode_get,
2601352f7f91STakashi Iwai 	.put = automute_mode_put,
2602352f7f91STakashi Iwai };
2603352f7f91STakashi Iwai 
2604352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
2605352f7f91STakashi Iwai {
2606352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2607352f7f91STakashi Iwai 
260812c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
2609352f7f91STakashi Iwai 		return -ENOMEM;
2610352f7f91STakashi Iwai 	return 0;
2611352f7f91STakashi Iwai }
2612352f7f91STakashi Iwai 
2613352f7f91STakashi Iwai /*
2614352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
2615352f7f91STakashi Iwai  * Set up appropriately if really supported
2616352f7f91STakashi Iwai  */
2617352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
2618352f7f91STakashi Iwai {
2619352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2620352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2621352f7f91STakashi Iwai 	int present = 0;
2622352f7f91STakashi Iwai 	int i, err;
2623352f7f91STakashi Iwai 
2624352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
2625352f7f91STakashi Iwai 		present++;
2626352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
2627352f7f91STakashi Iwai 		present++;
2628352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
2629352f7f91STakashi Iwai 		present++;
2630352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
2631352f7f91STakashi Iwai 		return 0;
2632352f7f91STakashi Iwai 
2633352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
2634352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2635352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2636352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2637352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2638352f7f91STakashi Iwai 	}
2639352f7f91STakashi Iwai 
2640352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
2641352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2642352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
2643352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
2644352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
2645352f7f91STakashi Iwai 	}
2646352f7f91STakashi Iwai 
2647352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
2648352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
2649352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
2650352f7f91STakashi Iwai 			continue;
2651352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
2652352f7f91STakashi Iwai 			    nid);
2653352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
26545d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
2655352f7f91STakashi Iwai 		spec->detect_hp = 1;
2656352f7f91STakashi Iwai 	}
2657352f7f91STakashi Iwai 
2658352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
2659352f7f91STakashi Iwai 		if (cfg->speaker_outs)
2660352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
2661352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
2662352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
2663352f7f91STakashi Iwai 					continue;
2664352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
2665352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
2666352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
26675d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
2668352f7f91STakashi Iwai 				spec->detect_lo = 1;
2669352f7f91STakashi Iwai 			}
2670352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
2671352f7f91STakashi Iwai 	}
2672352f7f91STakashi Iwai 
2673352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
2674352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
2675352f7f91STakashi Iwai 
2676352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
2677352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
2678352f7f91STakashi Iwai 
2679352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
2680352f7f91STakashi Iwai 		/* create a control for automute mode */
2681352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
2682352f7f91STakashi Iwai 		if (err < 0)
2683352f7f91STakashi Iwai 			return err;
2684352f7f91STakashi Iwai 	}
2685352f7f91STakashi Iwai 	return 0;
2686352f7f91STakashi Iwai }
2687352f7f91STakashi Iwai 
2688352f7f91STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2689352f7f91STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2690352f7f91STakashi Iwai {
2691352f7f91STakashi Iwai 	int i;
2692352f7f91STakashi Iwai 	for (i = 0; i < nums; i++)
2693352f7f91STakashi Iwai 		if (list[i] == nid)
2694352f7f91STakashi Iwai 			return i;
2695352f7f91STakashi Iwai 	return -1;
2696352f7f91STakashi Iwai }
2697352f7f91STakashi Iwai 
2698352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
2699352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
2700352f7f91STakashi Iwai {
2701352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2702352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2703352f7f91STakashi Iwai 	int i;
2704352f7f91STakashi Iwai 
2705352f7f91STakashi Iwai 	imux = &spec->input_mux;
2706352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
2707352f7f91STakashi Iwai 		spec->am_entry[i].idx =
2708352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
2709352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
2710352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
2711352f7f91STakashi Iwai 			return false; /* no corresponding imux */
2712352f7f91STakashi Iwai 	}
2713352f7f91STakashi Iwai 
2714352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
2715352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
2716352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
2717352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
2718352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
27195d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
2720352f7f91STakashi Iwai 	return true;
2721352f7f91STakashi Iwai }
2722352f7f91STakashi Iwai 
2723352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
2724352f7f91STakashi Iwai {
2725352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
2726352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
2727352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
2728352f7f91STakashi Iwai }
2729352f7f91STakashi Iwai 
2730352f7f91STakashi Iwai /*
2731352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
2732352f7f91STakashi Iwai  * Set up if really supported
2733352f7f91STakashi Iwai  */
2734352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
2735352f7f91STakashi Iwai {
2736352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2737352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2738352f7f91STakashi Iwai 	unsigned int types;
2739352f7f91STakashi Iwai 	int i, num_pins;
2740352f7f91STakashi Iwai 
2741352f7f91STakashi Iwai 	types = 0;
2742352f7f91STakashi Iwai 	num_pins = 0;
2743352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2744352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
2745352f7f91STakashi Iwai 		unsigned int attr;
2746352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
2747352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
2748352f7f91STakashi Iwai 		if (types & (1 << attr))
2749352f7f91STakashi Iwai 			return 0; /* already occupied */
2750352f7f91STakashi Iwai 		switch (attr) {
2751352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
2752352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
2753352f7f91STakashi Iwai 				return 0; /* invalid type */
2754352f7f91STakashi Iwai 			break;
2755352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
2756352f7f91STakashi Iwai 			return 0; /* invalid entry */
2757352f7f91STakashi Iwai 		default:
2758352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
2759352f7f91STakashi Iwai 				return 0; /* invalid type */
2760352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
2761352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
2762352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
2763352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
2764352f7f91STakashi Iwai 				return 0; /* no unsol support */
2765352f7f91STakashi Iwai 			break;
2766352f7f91STakashi Iwai 		}
2767352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
2768352f7f91STakashi Iwai 			return 0;
2769352f7f91STakashi Iwai 		types |= (1 << attr);
2770352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
2771352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
2772352f7f91STakashi Iwai 		num_pins++;
2773352f7f91STakashi Iwai 	}
2774352f7f91STakashi Iwai 
2775352f7f91STakashi Iwai 	if (num_pins < 2)
2776352f7f91STakashi Iwai 		return 0;
2777352f7f91STakashi Iwai 
2778352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
2779352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
2780352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
2781352f7f91STakashi Iwai 	 */
2782352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
2783352f7f91STakashi Iwai 	     compare_attr, NULL);
2784352f7f91STakashi Iwai 
2785352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
2786352f7f91STakashi Iwai 		return 0;
2787352f7f91STakashi Iwai 
2788352f7f91STakashi Iwai 	spec->auto_mic = 1;
2789352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
2790352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
2791352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
2792352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
2793352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
2794352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
2795352f7f91STakashi Iwai 
2796352f7f91STakashi Iwai 	return 0;
2797352f7f91STakashi Iwai }
2798352f7f91STakashi Iwai 
2799352f7f91STakashi Iwai 
28009eb413e5STakashi Iwai /*
28019eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
28029eb413e5STakashi Iwai  *
28039eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
2804352f7f91STakashi Iwai  * or a negative error code
2805352f7f91STakashi Iwai  */
2806352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
28079eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
2808352f7f91STakashi Iwai {
2809352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2810352f7f91STakashi Iwai 	int err;
2811352f7f91STakashi Iwai 
28129eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
28139eb413e5STakashi Iwai 		spec->autocfg = *cfg;
28149eb413e5STakashi Iwai 		cfg = &spec->autocfg;
28159eb413e5STakashi Iwai 	}
28169eb413e5STakashi Iwai 
2817352f7f91STakashi Iwai 	if (!cfg->line_outs) {
2818352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
2819352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
2820352f7f91STakashi Iwai 			spec->no_analog = 1;
2821352f7f91STakashi Iwai 			goto dig_only;
2822352f7f91STakashi Iwai 		}
2823352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
2824352f7f91STakashi Iwai 	}
2825352f7f91STakashi Iwai 
2826352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
2827352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
2828352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
2829352f7f91STakashi Iwai 		/* use HP as primary out */
2830352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
2831352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
2832352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
2833352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
2834352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
2835352f7f91STakashi Iwai 		cfg->hp_outs = 0;
2836352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2837352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
2838352f7f91STakashi Iwai 	}
2839352f7f91STakashi Iwai 
2840352f7f91STakashi Iwai 	err = parse_output_paths(codec);
2841352f7f91STakashi Iwai 	if (err < 0)
2842352f7f91STakashi Iwai 		return err;
2843352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
2844352f7f91STakashi Iwai 	if (err < 0)
2845352f7f91STakashi Iwai 		return err;
2846352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
2847352f7f91STakashi Iwai 	if (err < 0)
2848352f7f91STakashi Iwai 		return err;
2849352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
2850352f7f91STakashi Iwai 	if (err < 0)
2851352f7f91STakashi Iwai 		return err;
2852352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
2853352f7f91STakashi Iwai 	if (err < 0)
2854352f7f91STakashi Iwai 		return err;
2855352f7f91STakashi Iwai 	err = create_shared_input(codec);
2856352f7f91STakashi Iwai 	if (err < 0)
2857352f7f91STakashi Iwai 		return err;
2858352f7f91STakashi Iwai 	err = create_input_ctls(codec);
2859352f7f91STakashi Iwai 	if (err < 0)
2860352f7f91STakashi Iwai 		return err;
2861352f7f91STakashi Iwai 
2862352f7f91STakashi Iwai 	/* check the multiple speaker pins */
2863352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2864352f7f91STakashi Iwai 		spec->const_channel_count = cfg->line_outs * 2;
2865352f7f91STakashi Iwai 	else
2866352f7f91STakashi Iwai 		spec->const_channel_count = cfg->speaker_outs * 2;
2867352f7f91STakashi Iwai 
2868352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
2869352f7f91STakashi Iwai 		spec->multiout.max_channels = max(spec->ext_channel_count,
2870352f7f91STakashi Iwai 						  spec->const_channel_count);
2871352f7f91STakashi Iwai 	else
2872352f7f91STakashi Iwai 		spec->multiout.max_channels = spec->multiout.num_dacs * 2;
2873352f7f91STakashi Iwai 
2874352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
2875352f7f91STakashi Iwai 	if (err < 0)
2876352f7f91STakashi Iwai 		return err;
2877352f7f91STakashi Iwai 
2878352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
2879352f7f91STakashi Iwai 	if (err < 0)
2880352f7f91STakashi Iwai 		return err;
2881352f7f91STakashi Iwai 
2882352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
2883352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
2884352f7f91STakashi Iwai 		if (err < 0)
2885352f7f91STakashi Iwai 			return err;
2886352f7f91STakashi Iwai 	}
2887352f7f91STakashi Iwai 
2888352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
2889352f7f91STakashi Iwai 	if (err < 0)
2890352f7f91STakashi Iwai 		return err;
2891352f7f91STakashi Iwai 
2892352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
2893352f7f91STakashi Iwai 	if (err < 0)
2894352f7f91STakashi Iwai 		return err;
2895352f7f91STakashi Iwai 
2896352f7f91STakashi Iwai  dig_only:
2897352f7f91STakashi Iwai 	parse_digital(codec);
2898352f7f91STakashi Iwai 
2899352f7f91STakashi Iwai 	return 1;
2900352f7f91STakashi Iwai }
2901352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
2902352f7f91STakashi Iwai 
2903352f7f91STakashi Iwai 
2904352f7f91STakashi Iwai /*
2905352f7f91STakashi Iwai  * Build control elements
2906352f7f91STakashi Iwai  */
2907352f7f91STakashi Iwai 
2908352f7f91STakashi Iwai /* slave controls for virtual master */
2909352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
2910352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
2911352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
2912352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
2913352f7f91STakashi Iwai 	NULL,
2914352f7f91STakashi Iwai };
2915352f7f91STakashi Iwai 
2916352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
2917352f7f91STakashi Iwai {
2918352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2919352f7f91STakashi Iwai 	int err;
2920352f7f91STakashi Iwai 
292136502d02STakashi Iwai 	if (spec->kctls.used) {
2922352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
2923352f7f91STakashi Iwai 		if (err < 0)
2924352f7f91STakashi Iwai 			return err;
292536502d02STakashi Iwai 	}
2926352f7f91STakashi Iwai 
2927352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
2928352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
2929352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
2930352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
2931352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
2932352f7f91STakashi Iwai 		if (err < 0)
2933352f7f91STakashi Iwai 			return err;
2934352f7f91STakashi Iwai 		if (!spec->no_analog) {
2935352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
2936352f7f91STakashi Iwai 							    &spec->multiout);
2937352f7f91STakashi Iwai 			if (err < 0)
2938352f7f91STakashi Iwai 				return err;
2939352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
2940352f7f91STakashi Iwai 		}
2941352f7f91STakashi Iwai 	}
2942352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
2943352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
2944352f7f91STakashi Iwai 		if (err < 0)
2945352f7f91STakashi Iwai 			return err;
2946352f7f91STakashi Iwai 	}
2947352f7f91STakashi Iwai 
2948352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
2949352f7f91STakashi Iwai 	if (!spec->no_analog &&
2950352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
2951352f7f91STakashi Iwai 		unsigned int vmaster_tlv[4];
2952352f7f91STakashi Iwai 		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
2953352f7f91STakashi Iwai 					HDA_OUTPUT, vmaster_tlv);
2954352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
2955352f7f91STakashi Iwai 					  vmaster_tlv, slave_pfxs,
2956352f7f91STakashi Iwai 					  "Playback Volume");
2957352f7f91STakashi Iwai 		if (err < 0)
2958352f7f91STakashi Iwai 			return err;
2959352f7f91STakashi Iwai 	}
2960352f7f91STakashi Iwai 	if (!spec->no_analog &&
2961352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
2962352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
2963352f7f91STakashi Iwai 					    NULL, slave_pfxs,
2964352f7f91STakashi Iwai 					    "Playback Switch",
2965352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
2966352f7f91STakashi Iwai 		if (err < 0)
2967352f7f91STakashi Iwai 			return err;
2968352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
2969fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
2970fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
2971352f7f91STakashi Iwai 	}
2972352f7f91STakashi Iwai 
2973352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
2974352f7f91STakashi Iwai 
2975352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
2976352f7f91STakashi Iwai 		int err;
2977352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
2978352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
2979352f7f91STakashi Iwai 		if (err < 0)
2980352f7f91STakashi Iwai 			return err;
2981352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
2982352f7f91STakashi Iwai 		if (err < 0)
2983352f7f91STakashi Iwai 			return err;
2984352f7f91STakashi Iwai 	}
2985352f7f91STakashi Iwai 
2986352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
2987352f7f91STakashi Iwai 	if (err < 0)
2988352f7f91STakashi Iwai 		return err;
2989352f7f91STakashi Iwai 
2990352f7f91STakashi Iwai 	return 0;
2991352f7f91STakashi Iwai }
2992352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
2993352f7f91STakashi Iwai 
2994352f7f91STakashi Iwai 
2995352f7f91STakashi Iwai /*
2996352f7f91STakashi Iwai  * PCM definitions
2997352f7f91STakashi Iwai  */
2998352f7f91STakashi Iwai 
2999352f7f91STakashi Iwai /*
3000352f7f91STakashi Iwai  * Analog playback callbacks
3001352f7f91STakashi Iwai  */
3002352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3003352f7f91STakashi Iwai 			     struct hda_codec *codec,
3004352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3005352f7f91STakashi Iwai {
3006352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3007352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
3008352f7f91STakashi Iwai 					     hinfo);
3009352f7f91STakashi Iwai }
3010352f7f91STakashi Iwai 
3011352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
301297ec558aSTakashi Iwai 				struct hda_codec *codec,
301397ec558aSTakashi Iwai 				unsigned int stream_tag,
301497ec558aSTakashi Iwai 				unsigned int format,
301597ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
301697ec558aSTakashi Iwai {
3017352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3018352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3019352f7f91STakashi Iwai 						stream_tag, format, substream);
3020352f7f91STakashi Iwai }
302197ec558aSTakashi Iwai 
3022352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3023352f7f91STakashi Iwai 				struct hda_codec *codec,
3024352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3025352f7f91STakashi Iwai {
3026352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3027352f7f91STakashi Iwai 	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3028352f7f91STakashi Iwai }
3029352f7f91STakashi Iwai 
3030352f7f91STakashi Iwai /*
3031352f7f91STakashi Iwai  * Digital out
3032352f7f91STakashi Iwai  */
3033352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
3034352f7f91STakashi Iwai 				 struct hda_codec *codec,
3035352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
3036352f7f91STakashi Iwai {
3037352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3038352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
3039352f7f91STakashi Iwai }
3040352f7f91STakashi Iwai 
3041352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
3042352f7f91STakashi Iwai 				    struct hda_codec *codec,
3043352f7f91STakashi Iwai 				    unsigned int stream_tag,
3044352f7f91STakashi Iwai 				    unsigned int format,
3045352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3046352f7f91STakashi Iwai {
3047352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3048352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
3049352f7f91STakashi Iwai 					     stream_tag, format, substream);
3050352f7f91STakashi Iwai }
3051352f7f91STakashi Iwai 
3052352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3053352f7f91STakashi Iwai 				    struct hda_codec *codec,
3054352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
3055352f7f91STakashi Iwai {
3056352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3057352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
3058352f7f91STakashi Iwai }
3059352f7f91STakashi Iwai 
3060352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
3061352f7f91STakashi Iwai 				  struct hda_codec *codec,
3062352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
3063352f7f91STakashi Iwai {
3064352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3065352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
3066352f7f91STakashi Iwai }
3067352f7f91STakashi Iwai 
3068352f7f91STakashi Iwai /*
3069352f7f91STakashi Iwai  * Analog capture
3070352f7f91STakashi Iwai  */
3071352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3072352f7f91STakashi Iwai 				   struct hda_codec *codec,
3073352f7f91STakashi Iwai 				   unsigned int stream_tag,
3074352f7f91STakashi Iwai 				   unsigned int format,
3075352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
3076352f7f91STakashi Iwai {
3077352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3078352f7f91STakashi Iwai 
3079352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
308097ec558aSTakashi Iwai 				   stream_tag, 0, format);
308197ec558aSTakashi Iwai 	return 0;
308297ec558aSTakashi Iwai }
308397ec558aSTakashi Iwai 
3084352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
308597ec558aSTakashi Iwai 				   struct hda_codec *codec,
308697ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
308797ec558aSTakashi Iwai {
3088352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
308997ec558aSTakashi Iwai 
3090352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
3091352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
309297ec558aSTakashi Iwai 	return 0;
309397ec558aSTakashi Iwai }
309497ec558aSTakashi Iwai 
3095352f7f91STakashi Iwai /*
3096352f7f91STakashi Iwai  */
3097352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
3098352f7f91STakashi Iwai 	.substreams = 1,
3099352f7f91STakashi Iwai 	.channels_min = 2,
3100352f7f91STakashi Iwai 	.channels_max = 8,
3101352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3102352f7f91STakashi Iwai 	.ops = {
3103352f7f91STakashi Iwai 		.open = playback_pcm_open,
3104352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
3105352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
3106352f7f91STakashi Iwai 	},
3107352f7f91STakashi Iwai };
3108352f7f91STakashi Iwai 
3109352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
3110352f7f91STakashi Iwai 	.substreams = 1,
3111352f7f91STakashi Iwai 	.channels_min = 2,
3112352f7f91STakashi Iwai 	.channels_max = 2,
3113352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3114352f7f91STakashi Iwai };
3115352f7f91STakashi Iwai 
3116352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
3117352f7f91STakashi Iwai 	.substreams = 1,
3118352f7f91STakashi Iwai 	.channels_min = 2,
3119352f7f91STakashi Iwai 	.channels_max = 2,
3120352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3121352f7f91STakashi Iwai };
3122352f7f91STakashi Iwai 
3123352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
3124352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
3125352f7f91STakashi Iwai 	.channels_min = 2,
3126352f7f91STakashi Iwai 	.channels_max = 2,
3127352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3128352f7f91STakashi Iwai 	.ops = {
3129352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
3130352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
3131352f7f91STakashi Iwai 	},
3132352f7f91STakashi Iwai };
3133352f7f91STakashi Iwai 
3134352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
3135352f7f91STakashi Iwai 	.substreams = 1,
3136352f7f91STakashi Iwai 	.channels_min = 2,
3137352f7f91STakashi Iwai 	.channels_max = 2,
3138352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3139352f7f91STakashi Iwai 	.ops = {
3140352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
3141352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
3142352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
3143352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
3144352f7f91STakashi Iwai 	},
3145352f7f91STakashi Iwai };
3146352f7f91STakashi Iwai 
3147352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
3148352f7f91STakashi Iwai 	.substreams = 1,
3149352f7f91STakashi Iwai 	.channels_min = 2,
3150352f7f91STakashi Iwai 	.channels_max = 2,
3151352f7f91STakashi Iwai 	/* NID is set in build_pcms */
3152352f7f91STakashi Iwai };
3153352f7f91STakashi Iwai 
3154352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
3155352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
3156352f7f91STakashi Iwai 	.substreams = 0,
3157352f7f91STakashi Iwai 	.channels_min = 0,
3158352f7f91STakashi Iwai 	.channels_max = 0,
3159352f7f91STakashi Iwai };
3160352f7f91STakashi Iwai 
3161352f7f91STakashi Iwai /*
3162352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
3163352f7f91STakashi Iwai  */
3164352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
31651da177e4SLinus Torvalds {
3166352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3167352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
31681da177e4SLinus Torvalds 
3169352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
3170352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
3171352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
3172352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
3173352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
3174352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
3175352f7f91STakashi Iwai 					   spec->cur_adc_format);
3176352f7f91STakashi Iwai 		return true;
3177352f7f91STakashi Iwai 	}
3178352f7f91STakashi Iwai 	return false;
3179352f7f91STakashi Iwai }
3180352f7f91STakashi Iwai 
3181352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
3182352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3183352f7f91STakashi Iwai 				       struct hda_codec *codec,
3184352f7f91STakashi Iwai 				       unsigned int stream_tag,
3185352f7f91STakashi Iwai 				       unsigned int format,
3186352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3187352f7f91STakashi Iwai {
3188352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3189352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
3190352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
3191352f7f91STakashi Iwai 	spec->cur_adc_format = format;
3192352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
31931da177e4SLinus Torvalds 	return 0;
31941da177e4SLinus Torvalds }
31951da177e4SLinus Torvalds 
3196352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3197352f7f91STakashi Iwai 				       struct hda_codec *codec,
3198352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
3199352f7f91STakashi Iwai {
3200352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3201352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
3202352f7f91STakashi Iwai 	spec->cur_adc = 0;
3203352f7f91STakashi Iwai 	return 0;
3204352f7f91STakashi Iwai }
3205352f7f91STakashi Iwai 
3206352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
3207352f7f91STakashi Iwai 	.substreams = 1,
3208352f7f91STakashi Iwai 	.channels_min = 2,
3209352f7f91STakashi Iwai 	.channels_max = 2,
3210352f7f91STakashi Iwai 	.nid = 0, /* fill later */
3211352f7f91STakashi Iwai 	.ops = {
3212352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
3213352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
3214352f7f91STakashi Iwai 	},
3215352f7f91STakashi Iwai };
3216352f7f91STakashi Iwai 
3217352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
3218352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
3219352f7f91STakashi Iwai {
3220352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3221352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
3222352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
3223352f7f91STakashi Iwai 	bool have_multi_adcs;
3224352f7f91STakashi Iwai 	int i;
3225352f7f91STakashi Iwai 
32261da177e4SLinus Torvalds 	codec->num_pcms = 1;
32271da177e4SLinus Torvalds 	codec->pcm_info = info;
32281da177e4SLinus Torvalds 
3229352f7f91STakashi Iwai 	if (spec->no_analog)
3230352f7f91STakashi Iwai 		goto skip_analog;
3231352f7f91STakashi Iwai 
3232352f7f91STakashi Iwai 	snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
3233352f7f91STakashi Iwai 		 "%s Analog", codec->chip_name);
3234352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
3235352f7f91STakashi Iwai 
3236352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
3237352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
3238352f7f91STakashi Iwai 		if (!p)
3239352f7f91STakashi Iwai 			p = &pcm_analog_playback;
3240352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3241352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
3242352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
3243352f7f91STakashi Iwai 			spec->multiout.max_channels;
3244352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
3245352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
3246352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
3247352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
3248352f7f91STakashi Iwai 	}
3249352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
3250352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
3251352f7f91STakashi Iwai 		if (!p) {
3252352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
3253352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
3254352f7f91STakashi Iwai 			else
3255352f7f91STakashi Iwai 				p = &pcm_analog_capture;
3256352f7f91STakashi Iwai 		}
3257352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3258352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
3259352f7f91STakashi Iwai 	}
3260352f7f91STakashi Iwai 
3261352f7f91STakashi Iwai 	if (spec->channel_mode) {
3262352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
3263352f7f91STakashi Iwai 		for (i = 0; i < spec->num_channel_mode; i++) {
3264352f7f91STakashi Iwai 			if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
3265352f7f91STakashi Iwai 				info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
326697ec558aSTakashi Iwai 			}
32671da177e4SLinus Torvalds 		}
3268352f7f91STakashi Iwai 	}
3269352f7f91STakashi Iwai 
3270352f7f91STakashi Iwai  skip_analog:
3271352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
3272352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
3273352f7f91STakashi Iwai 		snprintf(spec->stream_name_digital,
3274352f7f91STakashi Iwai 			 sizeof(spec->stream_name_digital),
3275352f7f91STakashi Iwai 			 "%s Digital", codec->chip_name);
3276352f7f91STakashi Iwai 		codec->num_pcms = 2;
3277352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
3278352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
3279352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
3280352f7f91STakashi Iwai 		if (spec->dig_out_type)
3281352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
3282352f7f91STakashi Iwai 		else
3283352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
3284352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
3285352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
3286352f7f91STakashi Iwai 			if (!p)
3287352f7f91STakashi Iwai 				p = &pcm_digital_playback;
3288352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3289352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
3290352f7f91STakashi Iwai 		}
3291352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
3292352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
3293352f7f91STakashi Iwai 			if (!p)
3294352f7f91STakashi Iwai 				p = &pcm_digital_capture;
3295352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3296352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
3297352f7f91STakashi Iwai 		}
3298352f7f91STakashi Iwai 	}
3299352f7f91STakashi Iwai 
3300352f7f91STakashi Iwai 	if (spec->no_analog)
3301352f7f91STakashi Iwai 		return 0;
3302352f7f91STakashi Iwai 
3303352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
3304352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
3305352f7f91STakashi Iwai 	 */
3306352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
3307352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
3308352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
3309352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
3310352f7f91STakashi Iwai 		codec->num_pcms = 3;
3311352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
3312352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
3313352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
3314352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
3315352f7f91STakashi Iwai 			if (!p)
3316352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
3317352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
3318352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
3319352f7f91STakashi Iwai 				spec->alt_dac_nid;
3320352f7f91STakashi Iwai 		} else {
3321352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
3322352f7f91STakashi Iwai 				pcm_null_stream;
3323352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
3324352f7f91STakashi Iwai 		}
3325352f7f91STakashi Iwai 		if (have_multi_adcs) {
3326352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
3327352f7f91STakashi Iwai 			if (!p)
3328352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
3329352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
3330352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
3331352f7f91STakashi Iwai 				spec->adc_nids[1];
3332352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
3333352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
3334352f7f91STakashi Iwai 		} else {
3335352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
3336352f7f91STakashi Iwai 				pcm_null_stream;
3337352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
3338352f7f91STakashi Iwai 		}
33391da177e4SLinus Torvalds 	}
33401da177e4SLinus Torvalds 
33411da177e4SLinus Torvalds 	return 0;
33421da177e4SLinus Torvalds }
3343352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
3344352f7f91STakashi Iwai 
3345352f7f91STakashi Iwai 
3346352f7f91STakashi Iwai /*
3347352f7f91STakashi Iwai  * Standard auto-parser initializations
3348352f7f91STakashi Iwai  */
3349352f7f91STakashi Iwai 
3350352f7f91STakashi Iwai /* configure the path from the given dac to the pin as the proper output */
3351352f7f91STakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, hda_nid_t pin,
3352352f7f91STakashi Iwai 				  int pin_type, hda_nid_t dac)
3353352f7f91STakashi Iwai {
3354731dc301STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3355352f7f91STakashi Iwai 	struct nid_path *path;
3356352f7f91STakashi Iwai 
3357352f7f91STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, pin, pin_type);
3358352f7f91STakashi Iwai 	path = snd_hda_get_nid_path(codec, dac, pin);
3359352f7f91STakashi Iwai 	if (!path)
3360352f7f91STakashi Iwai 		return;
3361352f7f91STakashi Iwai 	if (path->active)
3362352f7f91STakashi Iwai 		return;
3363352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, true);
3364731dc301STakashi Iwai 
3365731dc301STakashi Iwai 	if (!spec->own_eapd_ctl &&
3366731dc301STakashi Iwai 	    (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
3367731dc301STakashi Iwai 		snd_hda_codec_update_cache(codec, pin, 0,
3368731dc301STakashi Iwai 					   AC_VERB_SET_EAPD_BTLENABLE, 0x02);
3369352f7f91STakashi Iwai }
3370352f7f91STakashi Iwai 
3371352f7f91STakashi Iwai /* initialize primary output paths */
3372352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
3373352f7f91STakashi Iwai {
3374352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3375352f7f91STakashi Iwai 	int pin_type;
3376352f7f91STakashi Iwai 	int i;
3377352f7f91STakashi Iwai 
3378352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3379352f7f91STakashi Iwai 		pin_type = PIN_HP;
3380352f7f91STakashi Iwai 	else
3381352f7f91STakashi Iwai 		pin_type = PIN_OUT;
3382352f7f91STakashi Iwai 
3383352f7f91STakashi Iwai 	for (i = 0; i <= HDA_SIDE; i++) {
3384352f7f91STakashi Iwai 		hda_nid_t nid = spec->autocfg.line_out_pins[i];
3385352f7f91STakashi Iwai 		if (nid)
3386352f7f91STakashi Iwai 			set_output_and_unmute(codec, nid, pin_type,
3387352f7f91STakashi Iwai 					      spec->multiout.dac_nids[i]);
3388352f7f91STakashi Iwai 
3389352f7f91STakashi Iwai 	}
3390352f7f91STakashi Iwai }
3391352f7f91STakashi Iwai 
3392352f7f91STakashi Iwai /* initialize hp and speaker paths */
3393352f7f91STakashi Iwai static void init_extra_out(struct hda_codec *codec)
3394352f7f91STakashi Iwai {
3395352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3396352f7f91STakashi Iwai 	int i;
3397352f7f91STakashi Iwai 	hda_nid_t pin, dac;
3398352f7f91STakashi Iwai 
3399352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.hp_outs; i++) {
3400352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
3401352f7f91STakashi Iwai 			break;
3402352f7f91STakashi Iwai 		pin = spec->autocfg.hp_pins[i];
3403352f7f91STakashi Iwai 		if (!pin)
3404352f7f91STakashi Iwai 			break;
3405352f7f91STakashi Iwai 		dac = spec->multiout.hp_out_nid[i];
3406352f7f91STakashi Iwai 		if (!dac) {
3407352f7f91STakashi Iwai 			if (i > 0 && spec->multiout.hp_out_nid[0])
3408352f7f91STakashi Iwai 				dac = spec->multiout.hp_out_nid[0];
3409352f7f91STakashi Iwai 			else
3410352f7f91STakashi Iwai 				dac = spec->multiout.dac_nids[0];
3411352f7f91STakashi Iwai 		}
3412352f7f91STakashi Iwai 		set_output_and_unmute(codec, pin, PIN_HP, dac);
3413352f7f91STakashi Iwai 	}
3414352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.speaker_outs; i++) {
3415352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3416352f7f91STakashi Iwai 			break;
3417352f7f91STakashi Iwai 		pin = spec->autocfg.speaker_pins[i];
3418352f7f91STakashi Iwai 		if (!pin)
3419352f7f91STakashi Iwai 			break;
3420352f7f91STakashi Iwai 		dac = spec->multiout.extra_out_nid[i];
3421352f7f91STakashi Iwai 		if (!dac) {
3422352f7f91STakashi Iwai 			if (i > 0 && spec->multiout.extra_out_nid[0])
3423352f7f91STakashi Iwai 				dac = spec->multiout.extra_out_nid[0];
3424352f7f91STakashi Iwai 			else
3425352f7f91STakashi Iwai 				dac = spec->multiout.dac_nids[0];
3426352f7f91STakashi Iwai 		}
3427352f7f91STakashi Iwai 		set_output_and_unmute(codec, pin, PIN_OUT, dac);
3428352f7f91STakashi Iwai 	}
3429352f7f91STakashi Iwai }
3430352f7f91STakashi Iwai 
3431352f7f91STakashi Iwai /* initialize multi-io paths */
3432352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
3433352f7f91STakashi Iwai {
3434352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3435352f7f91STakashi Iwai 	int i;
3436352f7f91STakashi Iwai 
3437352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
3438352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
3439352f7f91STakashi Iwai 		struct nid_path *path;
3440352f7f91STakashi Iwai 		path = snd_hda_get_nid_path(codec, spec->multi_io[i].dac, pin);
3441352f7f91STakashi Iwai 		if (!path)
3442352f7f91STakashi Iwai 			continue;
3443352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
3444352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
3445352f7f91STakashi Iwai 				snd_hda_codec_update_cache(codec, pin, 0,
3446352f7f91STakashi Iwai 					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
3447352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
3448352f7f91STakashi Iwai 	}
3449352f7f91STakashi Iwai }
3450352f7f91STakashi Iwai 
3451352f7f91STakashi Iwai /* set up the input pin config, depending on the given auto-pin type */
3452352f7f91STakashi Iwai static void set_input_pin(struct hda_codec *codec, hda_nid_t nid,
3453352f7f91STakashi Iwai 			  int auto_pin_type)
3454352f7f91STakashi Iwai {
3455352f7f91STakashi Iwai 	unsigned int val = PIN_IN;
3456352f7f91STakashi Iwai 	if (auto_pin_type == AUTO_PIN_MIC)
3457352f7f91STakashi Iwai 		val |= snd_hda_get_default_vref(codec, nid);
3458352f7f91STakashi Iwai 	snd_hda_set_pin_ctl(codec, nid, val);
3459352f7f91STakashi Iwai }
3460352f7f91STakashi Iwai 
3461352f7f91STakashi Iwai /* set up input pins and loopback paths */
3462352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
3463352f7f91STakashi Iwai {
3464352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3465352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3466352f7f91STakashi Iwai 	int i;
3467352f7f91STakashi Iwai 
3468352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3469352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3470352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
3471352f7f91STakashi Iwai 			set_input_pin(codec, nid, cfg->inputs[i].type);
3472352f7f91STakashi Iwai 
3473352f7f91STakashi Iwai 		/* init loopback inputs */
3474352f7f91STakashi Iwai 		if (spec->mixer_nid) {
3475352f7f91STakashi Iwai 			struct nid_path *path;
3476352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, spec->mixer_nid);
3477352f7f91STakashi Iwai 			if (path)
3478352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
3479352f7f91STakashi Iwai 						      path->active, false);
3480352f7f91STakashi Iwai 		}
3481352f7f91STakashi Iwai 	}
3482352f7f91STakashi Iwai }
3483352f7f91STakashi Iwai 
3484352f7f91STakashi Iwai /* initialize ADC paths */
3485352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
3486352f7f91STakashi Iwai {
3487352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3488352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3489352f7f91STakashi Iwai 	struct nid_path *path;
3490352f7f91STakashi Iwai 	int i, c, nums;
3491352f7f91STakashi Iwai 
3492352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3493352f7f91STakashi Iwai 		nums = 1;
3494352f7f91STakashi Iwai 	else
3495352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3496352f7f91STakashi Iwai 
3497352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
3498352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3499352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, spec->imux_pins[i],
3500352f7f91STakashi Iwai 						    get_adc_nid(codec, c, i));
3501352f7f91STakashi Iwai 			if (path) {
3502352f7f91STakashi Iwai 				bool active = path->active;
3503352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
3504352f7f91STakashi Iwai 					active = true;
3505352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
3506352f7f91STakashi Iwai 			}
3507352f7f91STakashi Iwai 		}
3508352f7f91STakashi Iwai 	}
3509352f7f91STakashi Iwai 
3510352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3511352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
3512352f7f91STakashi Iwai 
3513352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3514352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
3515352f7f91STakashi Iwai }
3516352f7f91STakashi Iwai 
3517352f7f91STakashi Iwai /* set right pin controls for digital I/O */
3518352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
3519352f7f91STakashi Iwai {
3520352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3521352f7f91STakashi Iwai 	int i;
3522352f7f91STakashi Iwai 	hda_nid_t pin;
3523352f7f91STakashi Iwai 
3524352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
3525352f7f91STakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3526352f7f91STakashi Iwai 		if (!pin)
3527352f7f91STakashi Iwai 			continue;
3528352f7f91STakashi Iwai 		set_output_and_unmute(codec, pin, PIN_OUT, 0);
3529352f7f91STakashi Iwai 	}
3530352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
3531352f7f91STakashi Iwai 	if (pin)
3532352f7f91STakashi Iwai 		snd_hda_set_pin_ctl(codec, pin, PIN_IN);
3533352f7f91STakashi Iwai }
3534352f7f91STakashi Iwai 
3535973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
3536973e4972STakashi Iwai  * invalid unsol tags by some reason
3537973e4972STakashi Iwai  */
3538973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
3539973e4972STakashi Iwai {
3540973e4972STakashi Iwai 	int i;
3541973e4972STakashi Iwai 
3542973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
3543973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
3544973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
3545973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
3546973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
3547973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
3548973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
3549973e4972STakashi Iwai 	}
3550973e4972STakashi Iwai }
3551973e4972STakashi Iwai 
3552352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
3553352f7f91STakashi Iwai {
3554352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3555352f7f91STakashi Iwai 
3556352f7f91STakashi Iwai 	if (spec->init_hook)
3557352f7f91STakashi Iwai 		spec->init_hook(codec);
3558352f7f91STakashi Iwai 
3559352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
3560352f7f91STakashi Iwai 
35613bbcd274STakashi Iwai 	codec->cached_write = 1;
35623bbcd274STakashi Iwai 
3563352f7f91STakashi Iwai 	init_multi_out(codec);
3564352f7f91STakashi Iwai 	init_extra_out(codec);
3565352f7f91STakashi Iwai 	init_multi_io(codec);
3566352f7f91STakashi Iwai 	init_analog_input(codec);
3567352f7f91STakashi Iwai 	init_input_src(codec);
3568352f7f91STakashi Iwai 	init_digital(codec);
3569352f7f91STakashi Iwai 
3570973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
3571973e4972STakashi Iwai 
3572352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
35735d550e15STakashi Iwai 	snd_hda_gen_hp_automute(codec, NULL);
35745d550e15STakashi Iwai 	snd_hda_gen_line_automute(codec, NULL);
35755d550e15STakashi Iwai 	snd_hda_gen_mic_autoswitch(codec, NULL);
3576352f7f91STakashi Iwai 
35773bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
35783bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
35793bbcd274STakashi Iwai 
3580352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
3581352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
3582352f7f91STakashi Iwai 
3583352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
3584352f7f91STakashi Iwai 	return 0;
3585352f7f91STakashi Iwai }
3586352f7f91STakashi Iwai EXPORT_SYMBOL(snd_hda_gen_init);
3587352f7f91STakashi Iwai 
3588352f7f91STakashi Iwai 
3589352f7f91STakashi Iwai /*
3590352f7f91STakashi Iwai  * the generic codec support
3591352f7f91STakashi Iwai  */
35921da177e4SLinus Torvalds 
359383012a7cSTakashi Iwai #ifdef CONFIG_PM
3594cb53c626STakashi Iwai static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid)
3595cb53c626STakashi Iwai {
3596352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3597cb53c626STakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
3598cb53c626STakashi Iwai }
3599cb53c626STakashi Iwai #endif
3600cb53c626STakashi Iwai 
3601352f7f91STakashi Iwai static void generic_free(struct hda_codec *codec)
3602352f7f91STakashi Iwai {
3603352f7f91STakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
3604352f7f91STakashi Iwai 	kfree(codec->spec);
3605352f7f91STakashi Iwai 	codec->spec = NULL;
3606352f7f91STakashi Iwai }
36071da177e4SLinus Torvalds 
3608352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
3609352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
3610352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
3611352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
3612352f7f91STakashi Iwai 	.free = generic_free,
3613352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
361483012a7cSTakashi Iwai #ifdef CONFIG_PM
3615cb53c626STakashi Iwai 	.check_power_status = generic_check_power_status,
3616cb53c626STakashi Iwai #endif
36171da177e4SLinus Torvalds };
36181da177e4SLinus Torvalds 
36191da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
36201da177e4SLinus Torvalds {
3621352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
36221da177e4SLinus Torvalds 	int err;
36231da177e4SLinus Torvalds 
3624e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
3625352f7f91STakashi Iwai 	if (!spec)
36261da177e4SLinus Torvalds 		return -ENOMEM;
3627352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
36281da177e4SLinus Torvalds 	codec->spec = spec;
36291da177e4SLinus Torvalds 
36309eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
36319eb413e5STakashi Iwai 	if (err < 0)
36329eb413e5STakashi Iwai 		return err;
36339eb413e5STakashi Iwai 
36349eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
3635352f7f91STakashi Iwai 	if (err < 0)
36361da177e4SLinus Torvalds 		goto error;
36371da177e4SLinus Torvalds 
36381da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
36391da177e4SLinus Torvalds 	return 0;
36401da177e4SLinus Torvalds 
36411da177e4SLinus Torvalds error:
3642352f7f91STakashi Iwai 	generic_free(codec);
36431da177e4SLinus Torvalds 	return err;
36441da177e4SLinus Torvalds }
36451289e9e8STakashi Iwai EXPORT_SYMBOL(snd_hda_parse_generic_codec);
3646