xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 8999bf0a)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Generic widget tree parser
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
71da177e4SLinus Torvalds  *
81da177e4SLinus Torvalds  *  This driver is free software; you can redistribute it and/or modify
91da177e4SLinus Torvalds  *  it under the terms of the GNU General Public License as published by
101da177e4SLinus Torvalds  *  the Free Software Foundation; either version 2 of the License, or
111da177e4SLinus Torvalds  *  (at your option) any later version.
121da177e4SLinus Torvalds  *
131da177e4SLinus Torvalds  *  This driver is distributed in the hope that it will be useful,
141da177e4SLinus Torvalds  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
151da177e4SLinus Torvalds  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
161da177e4SLinus Torvalds  *  GNU General Public License for more details.
171da177e4SLinus Torvalds  *
181da177e4SLinus Torvalds  *  You should have received a copy of the GNU General Public License
191da177e4SLinus Torvalds  *  along with this program; if not, write to the Free Software
201da177e4SLinus Torvalds  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
211da177e4SLinus Torvalds  */
221da177e4SLinus Torvalds 
231da177e4SLinus Torvalds #include <linux/init.h>
241da177e4SLinus Torvalds #include <linux/slab.h>
25d81a6d71SPaul Gortmaker #include <linux/export.h>
26352f7f91STakashi Iwai #include <linux/sort.h>
27f873e536STakashi Iwai #include <linux/ctype.h>
28f873e536STakashi Iwai #include <linux/string.h>
2929476558STakashi Iwai #include <linux/bitops.h>
301da177e4SLinus Torvalds #include <sound/core.h>
31352f7f91STakashi Iwai #include <sound/jack.h>
321da177e4SLinus Torvalds #include "hda_codec.h"
331da177e4SLinus Torvalds #include "hda_local.h"
34352f7f91STakashi Iwai #include "hda_auto_parser.h"
35352f7f91STakashi Iwai #include "hda_jack.h"
36352f7f91STakashi Iwai #include "hda_generic.h"
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds 
39352f7f91STakashi Iwai /* initialize hda_gen_spec struct */
40352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
411da177e4SLinus Torvalds {
42352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
43352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
4438cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
45352f7f91STakashi Iwai 	return 0;
46352f7f91STakashi Iwai }
47352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_init);
481da177e4SLinus Torvalds 
4912c93df6STakashi Iwai struct snd_kcontrol_new *
5012c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
51352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
52352f7f91STakashi Iwai {
53352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
54352f7f91STakashi Iwai 	if (!knew)
55352f7f91STakashi Iwai 		return NULL;
56352f7f91STakashi Iwai 	*knew = *temp;
57352f7f91STakashi Iwai 	if (name)
58352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
59352f7f91STakashi Iwai 	else if (knew->name)
60352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
61352f7f91STakashi Iwai 	if (!knew->name)
62352f7f91STakashi Iwai 		return NULL;
63352f7f91STakashi Iwai 	return knew;
64352f7f91STakashi Iwai }
6512c93df6STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_add_kctl);
66352f7f91STakashi Iwai 
67352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
68352f7f91STakashi Iwai {
69352f7f91STakashi Iwai 	if (spec->kctls.list) {
70352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
71352f7f91STakashi Iwai 		int i;
72352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
73352f7f91STakashi Iwai 			kfree(kctl[i].name);
74352f7f91STakashi Iwai 	}
75352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
76352f7f91STakashi Iwai }
77352f7f91STakashi Iwai 
78352f7f91STakashi Iwai void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
79352f7f91STakashi Iwai {
801da177e4SLinus Torvalds 	if (!spec)
811da177e4SLinus Torvalds 		return;
82352f7f91STakashi Iwai 	free_kctls(spec);
83352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
841da177e4SLinus Torvalds }
85352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);
861da177e4SLinus Torvalds 
871da177e4SLinus Torvalds /*
881c70a583STakashi Iwai  * store user hints
891c70a583STakashi Iwai  */
901c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
911c70a583STakashi Iwai {
921c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
931c70a583STakashi Iwai 	int val;
941c70a583STakashi Iwai 
951c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
961c70a583STakashi Iwai 	if (val >= 0)
971c70a583STakashi Iwai 		codec->no_jack_detect = !val;
981c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
991c70a583STakashi Iwai 	if (val >= 0)
1001c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1011c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1021c70a583STakashi Iwai 	if (val >= 0)
1031c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1041c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1051c70a583STakashi Iwai 	if (val >= 0)
1061c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1071c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1081c70a583STakashi Iwai 	if (val >= 0)
1091c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1101c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1111c70a583STakashi Iwai 	if (val >= 0)
1121c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1131c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1141c70a583STakashi Iwai 	if (val >= 0)
1151c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
1221c70a583STakashi Iwai 
123f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
124f72706beSTakashi Iwai 	if (val >= 0)
125f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1261c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1271c70a583STakashi Iwai 	if (val >= 0)
1281c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1291c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1301c70a583STakashi Iwai 	if (val >= 0)
1311c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1321c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1331c70a583STakashi Iwai 	if (val >= 0)
1341c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1351c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1361c70a583STakashi Iwai 	if (val >= 0)
1371c70a583STakashi Iwai 		spec->no_primary_hp = !val;
1381c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1391c70a583STakashi Iwai 	if (val >= 0)
1401c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1411c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1421c70a583STakashi Iwai 	if (val >= 0)
1431c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1441c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1451c70a583STakashi Iwai 	if (val >= 0)
1461c70a583STakashi Iwai 		spec->indep_hp = !!val;
1471c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1481c70a583STakashi Iwai 	if (val >= 0)
1491c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->add_out_jack_modes = !!val;
15329476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
15429476558STakashi Iwai 	if (val >= 0)
15529476558STakashi Iwai 		spec->add_in_jack_modes = !!val;
1561c70a583STakashi Iwai 
1571c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1581c70a583STakashi Iwai 		spec->mixer_nid = val;
1591c70a583STakashi Iwai }
1601c70a583STakashi Iwai 
1611c70a583STakashi Iwai /*
1622c12c30dSTakashi Iwai  * pin control value accesses
1632c12c30dSTakashi Iwai  */
1642c12c30dSTakashi Iwai 
1652c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
1662c12c30dSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0, \
1672c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
1682c12c30dSTakashi Iwai 
1692c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
1702c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
1712c12c30dSTakashi Iwai {
1722c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
1732c12c30dSTakashi Iwai }
1742c12c30dSTakashi Iwai 
1752c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
1762c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
1772c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
1782c12c30dSTakashi Iwai {
1792c12c30dSTakashi Iwai 	if (!pin)
1802c12c30dSTakashi Iwai 		return;
1812c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
1822c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
1832c12c30dSTakashi Iwai 	if (do_write)
1842c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
1852c12c30dSTakashi Iwai }
1862c12c30dSTakashi Iwai 
1872c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
1882c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
1892c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
1902c12c30dSTakashi Iwai {
1912c12c30dSTakashi Iwai 	int i;
1922c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
1932c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
1942c12c30dSTakashi Iwai }
1952c12c30dSTakashi Iwai 
1962c12c30dSTakashi Iwai /*
197352f7f91STakashi Iwai  * parsing paths
1981da177e4SLinus Torvalds  */
1991da177e4SLinus Torvalds 
2003ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2013ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2023ca529d3STakashi Iwai {
2033ca529d3STakashi Iwai 	int i;
2043ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2053ca529d3STakashi Iwai 		if (list[i] == nid)
2063ca529d3STakashi Iwai 			return i;
2073ca529d3STakashi Iwai 	return -1;
2083ca529d3STakashi Iwai }
2093ca529d3STakashi Iwai 
2103ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2113ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2123ca529d3STakashi Iwai {
2133ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2143ca529d3STakashi Iwai }
2153ca529d3STakashi Iwai 
216f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
217f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2183ca529d3STakashi Iwai 				     int anchor_nid)
2191da177e4SLinus Torvalds {
220352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
221352f7f91STakashi Iwai 	int i;
2221da177e4SLinus Torvalds 
223352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
224352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
225352f7f91STakashi Iwai 		if (path->depth <= 0)
226352f7f91STakashi Iwai 			continue;
227352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
228f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2293ca529d3STakashi Iwai 			if (!anchor_nid ||
2303ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2313ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
232352f7f91STakashi Iwai 				return path;
2331da177e4SLinus Torvalds 		}
234f5172a7eSTakashi Iwai 	}
2351da177e4SLinus Torvalds 	return NULL;
2361da177e4SLinus Torvalds }
237f5172a7eSTakashi Iwai 
238f5172a7eSTakashi Iwai /* get the path between the given NIDs;
239f5172a7eSTakashi Iwai  * passing 0 to either @pin or @dac behaves as a wildcard
240f5172a7eSTakashi Iwai  */
241f5172a7eSTakashi Iwai struct nid_path *snd_hda_get_nid_path(struct hda_codec *codec,
242f5172a7eSTakashi Iwai 				      hda_nid_t from_nid, hda_nid_t to_nid)
243f5172a7eSTakashi Iwai {
2443ca529d3STakashi Iwai 	return get_nid_path(codec, from_nid, to_nid, 0);
245f5172a7eSTakashi Iwai }
246352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_get_nid_path);
2471da177e4SLinus Torvalds 
248196c1766STakashi Iwai /* get the index number corresponding to the path instance;
249196c1766STakashi Iwai  * the index starts from 1, for easier checking the invalid value
250196c1766STakashi Iwai  */
251196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
252196c1766STakashi Iwai {
253196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
254196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
255196c1766STakashi Iwai 	ssize_t idx;
256196c1766STakashi Iwai 
257196c1766STakashi Iwai 	if (!spec->paths.used)
258196c1766STakashi Iwai 		return 0;
259196c1766STakashi Iwai 	idx = path - array;
260196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
261196c1766STakashi Iwai 		return 0;
262196c1766STakashi Iwai 	return idx + 1;
263196c1766STakashi Iwai }
264196c1766STakashi Iwai 
265196c1766STakashi Iwai /* get the path instance corresponding to the given index number */
266196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
267196c1766STakashi Iwai {
268196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
269196c1766STakashi Iwai 
270196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
271196c1766STakashi Iwai 		return NULL;
272196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
273196c1766STakashi Iwai }
274196c1766STakashi Iwai 
275352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
276352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
2771da177e4SLinus Torvalds {
278352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
279352f7f91STakashi Iwai 	int i;
280352f7f91STakashi Iwai 
281352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
282352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
283352f7f91STakashi Iwai 		if (path->path[0] == nid)
284352f7f91STakashi Iwai 			return true;
285352f7f91STakashi Iwai 	}
286352f7f91STakashi Iwai 	return false;
2871da177e4SLinus Torvalds }
2881da177e4SLinus Torvalds 
289352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
290352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
291352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
2921da177e4SLinus Torvalds {
293352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
294352f7f91STakashi Iwai 		return false;
295352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
2961da177e4SLinus Torvalds }
2971da177e4SLinus Torvalds 
298352f7f91STakashi Iwai /* nid, dir and idx */
299352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
300352f7f91STakashi Iwai 
301352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
302352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3031da177e4SLinus Torvalds {
304352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
305352f7f91STakashi Iwai 	int i;
306352f7f91STakashi Iwai 
307352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
308352f7f91STakashi Iwai 	for (i = 0; i < spec->paths.used; i++) {
309352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, i);
310352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
311352f7f91STakashi Iwai 			return true;
312352f7f91STakashi Iwai 	}
313352f7f91STakashi Iwai 	return false;
3141da177e4SLinus Torvalds }
3151da177e4SLinus Torvalds 
316352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
317352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3188999bf0aSTakashi Iwai 			      int dir, int idx, int type)
319cb53c626STakashi Iwai {
320352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3218999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
322cb53c626STakashi Iwai }
323352f7f91STakashi Iwai 
3240c8c0f56STakashi Iwai static void print_nid_path(const char *pfx, struct nid_path *path)
3250c8c0f56STakashi Iwai {
3260c8c0f56STakashi Iwai 	char buf[40];
3270c8c0f56STakashi Iwai 	int i;
3280c8c0f56STakashi Iwai 
3290c8c0f56STakashi Iwai 
3300c8c0f56STakashi Iwai 	buf[0] = 0;
3310c8c0f56STakashi Iwai 	for (i = 0; i < path->depth; i++) {
3320c8c0f56STakashi Iwai 		char tmp[4];
3330c8c0f56STakashi Iwai 		sprintf(tmp, ":%02x", path->path[i]);
3340c8c0f56STakashi Iwai 		strlcat(buf, tmp, sizeof(buf));
3350c8c0f56STakashi Iwai 	}
3360c8c0f56STakashi Iwai 	snd_printdd("%s path: depth=%d %s\n", pfx, path->depth, buf);
3370c8c0f56STakashi Iwai }
3380c8c0f56STakashi Iwai 
339352f7f91STakashi Iwai /* called recursively */
340352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
341352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3423ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3433ca529d3STakashi Iwai 			     int depth)
344352f7f91STakashi Iwai {
345ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
346352f7f91STakashi Iwai 	int i, nums;
347352f7f91STakashi Iwai 
3483ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3493ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3503ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3513ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
352352f7f91STakashi Iwai 
353ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
354352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
355352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
356352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
357352f7f91STakashi Iwai 			 * try to find an empty DAC
358352f7f91STakashi Iwai 			 */
359352f7f91STakashi Iwai 			if (from_nid ||
360352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
361352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
362352f7f91STakashi Iwai 				continue;
363352f7f91STakashi Iwai 		}
3643ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
3653ca529d3STakashi Iwai 		if (anchor_nid <= 0)
366352f7f91STakashi Iwai 			goto found;
367352f7f91STakashi Iwai 	}
368352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
369352f7f91STakashi Iwai 		return false;
370352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
371352f7f91STakashi Iwai 		unsigned int type;
372352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
373352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
374352f7f91STakashi Iwai 		    type == AC_WID_PIN)
375352f7f91STakashi Iwai 			continue;
376352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
3773ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
378352f7f91STakashi Iwai 			goto found;
379352f7f91STakashi Iwai 	}
380352f7f91STakashi Iwai 	return false;
381352f7f91STakashi Iwai 
382352f7f91STakashi Iwai  found:
383352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
384352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
385352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
386352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
387352f7f91STakashi Iwai 	path->depth++;
388352f7f91STakashi Iwai 	return true;
389352f7f91STakashi Iwai }
390352f7f91STakashi Iwai 
391352f7f91STakashi Iwai /* parse the widget path from the given nid to the target nid;
392352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
3933ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
3943ca529d3STakashi Iwai  * with the given value are evaluated.
3953ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
3963ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
3973ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
398352f7f91STakashi Iwai  */
399352f7f91STakashi Iwai bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4003ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
401352f7f91STakashi Iwai 			    struct nid_path *path)
402352f7f91STakashi Iwai {
4033ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
404352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
405352f7f91STakashi Iwai 		path->depth++;
406352f7f91STakashi Iwai 		return true;
407352f7f91STakashi Iwai 	}
408352f7f91STakashi Iwai 	return false;
409352f7f91STakashi Iwai }
410352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_nid_path);
411352f7f91STakashi Iwai 
412352f7f91STakashi Iwai /*
413352f7f91STakashi Iwai  * parse the path between the given NIDs and add to the path list.
414352f7f91STakashi Iwai  * if no valid path is found, return NULL
415352f7f91STakashi Iwai  */
416352f7f91STakashi Iwai struct nid_path *
417352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4183ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
419352f7f91STakashi Iwai {
420352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
421352f7f91STakashi Iwai 	struct nid_path *path;
422352f7f91STakashi Iwai 
423352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
424352f7f91STakashi Iwai 		return NULL;
425352f7f91STakashi Iwai 
426f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4273ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
428f5172a7eSTakashi Iwai 	if (path)
429f5172a7eSTakashi Iwai 		return path;
430f5172a7eSTakashi Iwai 
431352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
432352f7f91STakashi Iwai 	if (!path)
433352f7f91STakashi Iwai 		return NULL;
434352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4353ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
436352f7f91STakashi Iwai 		return path;
437352f7f91STakashi Iwai 	/* push back */
438352f7f91STakashi Iwai 	spec->paths.used--;
439352f7f91STakashi Iwai 	return NULL;
440352f7f91STakashi Iwai }
441352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_add_new_path);
442352f7f91STakashi Iwai 
443980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
444980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
445980428ceSTakashi Iwai {
446980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
447980428ceSTakashi Iwai 	if (!path)
448980428ceSTakashi Iwai 		return;
449980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
450980428ceSTakashi Iwai }
451980428ceSTakashi Iwai 
452352f7f91STakashi Iwai /* look for an empty DAC slot */
453352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
454352f7f91STakashi Iwai 			      bool is_digital)
455352f7f91STakashi Iwai {
456352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
457352f7f91STakashi Iwai 	bool cap_digital;
458352f7f91STakashi Iwai 	int i;
459352f7f91STakashi Iwai 
460352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
461352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
462352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
463352f7f91STakashi Iwai 			continue;
464352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
465352f7f91STakashi Iwai 		if (is_digital != cap_digital)
466352f7f91STakashi Iwai 			continue;
467352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
468352f7f91STakashi Iwai 			return nid;
469352f7f91STakashi Iwai 	}
470352f7f91STakashi Iwai 	return 0;
471352f7f91STakashi Iwai }
472352f7f91STakashi Iwai 
473352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
474352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
475352f7f91STakashi Iwai {
476352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
477352f7f91STakashi Iwai 	val |= chs << 16;
478352f7f91STakashi Iwai 	return val;
479352f7f91STakashi Iwai }
480352f7f91STakashi Iwai 
481352f7f91STakashi Iwai /* check whether the widget has the given amp capability for the direction */
482352f7f91STakashi Iwai static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
483352f7f91STakashi Iwai 			   int dir, unsigned int bits)
484352f7f91STakashi Iwai {
485352f7f91STakashi Iwai 	if (!nid)
486352f7f91STakashi Iwai 		return false;
487352f7f91STakashi Iwai 	if (get_wcaps(codec, nid) & (1 << (dir + 1)))
488352f7f91STakashi Iwai 		if (query_amp_caps(codec, nid, dir) & bits)
489352f7f91STakashi Iwai 			return true;
490352f7f91STakashi Iwai 	return false;
491352f7f91STakashi Iwai }
492352f7f91STakashi Iwai 
49399a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
49499a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
49599a5592dSDavid Henningsson {
49699a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
49799a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
49899a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
49999a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
50099a5592dSDavid Henningsson }
50199a5592dSDavid Henningsson 
502352f7f91STakashi Iwai #define nid_has_mute(codec, nid, dir) \
503352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
504352f7f91STakashi Iwai #define nid_has_volume(codec, nid, dir) \
505352f7f91STakashi Iwai 	check_amp_caps(codec, nid, dir, AC_AMPCAP_NUM_STEPS)
506352f7f91STakashi Iwai 
507352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
508352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
509352f7f91STakashi Iwai 				       struct nid_path *path)
510352f7f91STakashi Iwai {
511352f7f91STakashi Iwai 	int i;
512352f7f91STakashi Iwai 
513352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
514352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
515352f7f91STakashi Iwai 			return path->path[i];
516352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
517352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
518352f7f91STakashi Iwai 			return path->path[i];
519352f7f91STakashi Iwai 	}
520352f7f91STakashi Iwai 	return 0;
521352f7f91STakashi Iwai }
522352f7f91STakashi Iwai 
523352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
524352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
525352f7f91STakashi Iwai 				      struct nid_path *path)
526352f7f91STakashi Iwai {
527352f7f91STakashi Iwai 	int i;
528352f7f91STakashi Iwai 
529352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
530352f7f91STakashi Iwai 		if (nid_has_volume(codec, path->path[i], HDA_OUTPUT))
531352f7f91STakashi Iwai 			return path->path[i];
532352f7f91STakashi Iwai 	}
533352f7f91STakashi Iwai 	return 0;
534352f7f91STakashi Iwai }
535352f7f91STakashi Iwai 
536352f7f91STakashi Iwai /*
537352f7f91STakashi Iwai  * path activation / deactivation
538352f7f91STakashi Iwai  */
539352f7f91STakashi Iwai 
540352f7f91STakashi Iwai /* can have the amp-in capability? */
541352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
542352f7f91STakashi Iwai {
543352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
544352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
545352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
546352f7f91STakashi Iwai 
547352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
548352f7f91STakashi Iwai 		return false;
549352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
550352f7f91STakashi Iwai 		return false;
551352f7f91STakashi Iwai 	return true;
552352f7f91STakashi Iwai }
553352f7f91STakashi Iwai 
554352f7f91STakashi Iwai /* can have the amp-out capability? */
555352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
556352f7f91STakashi Iwai {
557352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
558352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
559352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
560352f7f91STakashi Iwai 
561352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
562352f7f91STakashi Iwai 		return false;
563352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
564352f7f91STakashi Iwai 		return false;
565352f7f91STakashi Iwai 	return true;
566352f7f91STakashi Iwai }
567352f7f91STakashi Iwai 
568352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
569352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
570352f7f91STakashi Iwai 			  unsigned int idx, unsigned int dir)
571352f7f91STakashi Iwai {
572352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
573352f7f91STakashi Iwai 	int i, n;
574352f7f91STakashi Iwai 
575352f7f91STakashi Iwai 	for (n = 0; n < spec->paths.used; n++) {
576352f7f91STakashi Iwai 		struct nid_path *path = snd_array_elem(&spec->paths, n);
577352f7f91STakashi Iwai 		if (!path->active)
578352f7f91STakashi Iwai 			continue;
579352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
580352f7f91STakashi Iwai 			if (path->path[i] == nid) {
581352f7f91STakashi Iwai 				if (dir == HDA_OUTPUT || path->idx[i] == idx)
582352f7f91STakashi Iwai 					return true;
583352f7f91STakashi Iwai 				break;
584352f7f91STakashi Iwai 			}
585352f7f91STakashi Iwai 		}
586352f7f91STakashi Iwai 	}
587352f7f91STakashi Iwai 	return false;
588352f7f91STakashi Iwai }
589352f7f91STakashi Iwai 
590352f7f91STakashi Iwai /* get the default amp value for the target state */
591352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
5928999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
593352f7f91STakashi Iwai {
594352f7f91STakashi Iwai 	unsigned int val = 0;
595352f7f91STakashi Iwai 
596352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
597352f7f91STakashi Iwai 		/* set to 0dB */
598352f7f91STakashi Iwai 		if (enable)
599352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
600352f7f91STakashi Iwai 	}
601352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
602352f7f91STakashi Iwai 		if (!enable)
603352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
604352f7f91STakashi Iwai 	}
605352f7f91STakashi Iwai 	return val;
606352f7f91STakashi Iwai }
607352f7f91STakashi Iwai 
608352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
609352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
610352f7f91STakashi Iwai {
6118999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
6128999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
613352f7f91STakashi Iwai 	snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
614352f7f91STakashi Iwai }
615352f7f91STakashi Iwai 
6168999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
6178999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
6188999bf0aSTakashi Iwai  */
6198999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
6208999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
6218999bf0aSTakashi Iwai 					   unsigned int caps)
622352f7f91STakashi Iwai {
6238999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
6248999bf0aSTakashi Iwai 
6258999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_MUTE) {
6268999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
6278999bf0aSTakashi Iwai 			mask &= ~0x80;
6288999bf0aSTakashi Iwai 	}
6298999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
6308999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
6318999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
6328999bf0aSTakashi Iwai 			mask &= ~0x7f;
6338999bf0aSTakashi Iwai 	}
6348999bf0aSTakashi Iwai 	return mask;
6358999bf0aSTakashi Iwai }
6368999bf0aSTakashi Iwai 
6378999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
6388999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
6398999bf0aSTakashi Iwai {
6408999bf0aSTakashi Iwai 	unsigned int caps;
6418999bf0aSTakashi Iwai 	unsigned int mask, val;
6428999bf0aSTakashi Iwai 
6438999bf0aSTakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx))
644352f7f91STakashi Iwai 		return;
6458999bf0aSTakashi Iwai 
6468999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
6478999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
6488999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
6498999bf0aSTakashi Iwai 	if (!mask)
6508999bf0aSTakashi Iwai 		return;
6518999bf0aSTakashi Iwai 
6528999bf0aSTakashi Iwai 	val &= mask;
6538999bf0aSTakashi Iwai 	snd_hda_codec_amp_stereo(codec, nid, dir, idx, mask, val);
654352f7f91STakashi Iwai }
655352f7f91STakashi Iwai 
656352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
657352f7f91STakashi Iwai 			     int i, bool enable)
658352f7f91STakashi Iwai {
659352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
660352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
6618999bf0aSTakashi Iwai 	activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
662352f7f91STakashi Iwai }
663352f7f91STakashi Iwai 
664352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
665352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
666352f7f91STakashi Iwai {
667352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
668ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
669352f7f91STakashi Iwai 	int n, nums, idx;
670352f7f91STakashi Iwai 	int type;
671352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
672352f7f91STakashi Iwai 
673ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
674352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
675352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
676352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
677352f7f91STakashi Iwai 		nums = 1;
678352f7f91STakashi Iwai 		idx = 0;
679352f7f91STakashi Iwai 	} else
680352f7f91STakashi Iwai 		idx = path->idx[i];
681352f7f91STakashi Iwai 
682352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
683352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
684352f7f91STakashi Iwai 
685352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
686352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
687352f7f91STakashi Iwai 	 */
688352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
689352f7f91STakashi Iwai 		if (n != idx && (!add_aamix || conn[n] != spec->mixer_nid))
690352f7f91STakashi Iwai 			continue;
6918999bf0aSTakashi Iwai 		activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
692352f7f91STakashi Iwai 	}
693352f7f91STakashi Iwai }
694352f7f91STakashi Iwai 
695352f7f91STakashi Iwai /* activate or deactivate the given path
696352f7f91STakashi Iwai  * if @add_aamix is set, enable the input from aa-mix NID as well (if any)
697352f7f91STakashi Iwai  */
698352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
699352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
700352f7f91STakashi Iwai {
701352f7f91STakashi Iwai 	int i;
702352f7f91STakashi Iwai 
703352f7f91STakashi Iwai 	if (!enable)
704352f7f91STakashi Iwai 		path->active = false;
705352f7f91STakashi Iwai 
706352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
707352f7f91STakashi Iwai 		if (enable && path->multi[i])
708352f7f91STakashi Iwai 			snd_hda_codec_write_cache(codec, path->path[i], 0,
709352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
710352f7f91STakashi Iwai 					    path->idx[i]);
711352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
712352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
713352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
714352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
715352f7f91STakashi Iwai 	}
716352f7f91STakashi Iwai 
717352f7f91STakashi Iwai 	if (enable)
718352f7f91STakashi Iwai 		path->active = true;
719352f7f91STakashi Iwai }
720352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_activate_path);
721352f7f91STakashi Iwai 
722d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
723d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
724d5a9f1bbSTakashi Iwai {
725d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
726d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
727d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
728d5a9f1bbSTakashi Iwai 		return;
729ecac3ed1STakashi Iwai 	if (codec->inv_eapd)
730ecac3ed1STakashi Iwai 		enable = !enable;
731d5a9f1bbSTakashi Iwai 	snd_hda_codec_update_cache(codec, pin, 0,
732d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
733d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
734d5a9f1bbSTakashi Iwai }
735d5a9f1bbSTakashi Iwai 
736352f7f91STakashi Iwai 
737352f7f91STakashi Iwai /*
738352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
739352f7f91STakashi Iwai  */
740352f7f91STakashi Iwai 
741352f7f91STakashi Iwai enum {
742352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
743352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
744352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
745352f7f91STakashi Iwai };
746352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
747352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
748352f7f91STakashi Iwai 	HDA_CODEC_MUTE(NULL, 0, 0, 0),
749352f7f91STakashi Iwai 	HDA_BIND_MUTE(NULL, 0, 0, 0),
750352f7f91STakashi Iwai };
751352f7f91STakashi Iwai 
752352f7f91STakashi Iwai /* add dynamic controls from template */
753352f7f91STakashi Iwai static int add_control(struct hda_gen_spec *spec, int type, const char *name,
754352f7f91STakashi Iwai 		       int cidx, unsigned long val)
755352f7f91STakashi Iwai {
756352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
757352f7f91STakashi Iwai 
75812c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
759352f7f91STakashi Iwai 	if (!knew)
760352f7f91STakashi Iwai 		return -ENOMEM;
761352f7f91STakashi Iwai 	knew->index = cidx;
762352f7f91STakashi Iwai 	if (get_amp_nid_(val))
763352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
764352f7f91STakashi Iwai 	knew->private_value = val;
765352f7f91STakashi Iwai 	return 0;
766352f7f91STakashi Iwai }
767352f7f91STakashi Iwai 
768352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
769352f7f91STakashi Iwai 				const char *pfx, const char *dir,
770352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
771352f7f91STakashi Iwai {
772352f7f91STakashi Iwai 	char name[32];
773352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
774352f7f91STakashi Iwai 	return add_control(spec, type, name, cidx, val);
775352f7f91STakashi Iwai }
776352f7f91STakashi Iwai 
777352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
778352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
779352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
780352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
781352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
782352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
783352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
784352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
785352f7f91STakashi Iwai 
786352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
787352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
788352f7f91STakashi Iwai {
789352f7f91STakashi Iwai 	unsigned int val;
790352f7f91STakashi Iwai 	if (!path)
791352f7f91STakashi Iwai 		return 0;
792352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
793352f7f91STakashi Iwai 	if (!val)
794352f7f91STakashi Iwai 		return 0;
795352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
796352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
797352f7f91STakashi Iwai }
798352f7f91STakashi Iwai 
799352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
800352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
801352f7f91STakashi Iwai 			       int type)
802352f7f91STakashi Iwai {
803352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
804352f7f91STakashi Iwai 	if (path) {
805352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
806352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
807352f7f91STakashi Iwai 			chs = 3; /* stereo */
808352f7f91STakashi Iwai 	}
809352f7f91STakashi Iwai 	return chs;
810352f7f91STakashi Iwai }
811352f7f91STakashi Iwai 
812352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
813352f7f91STakashi Iwai 			  struct nid_path *path)
814352f7f91STakashi Iwai {
815352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
816352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
817352f7f91STakashi Iwai }
818352f7f91STakashi Iwai 
819352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
820352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
821352f7f91STakashi Iwai  */
822352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
823352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
824352f7f91STakashi Iwai {
825352f7f91STakashi Iwai 	unsigned int val;
826352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
827352f7f91STakashi Iwai 
828352f7f91STakashi Iwai 	if (!path)
829352f7f91STakashi Iwai 		return 0;
830352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
831352f7f91STakashi Iwai 	if (!val)
832352f7f91STakashi Iwai 		return 0;
833352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
834352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
835352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
836352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
837352f7f91STakashi Iwai 		if (nums > 1) {
838352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
839352f7f91STakashi Iwai 			val |= nums << 19;
840352f7f91STakashi Iwai 		}
841352f7f91STakashi Iwai 	}
842352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
843352f7f91STakashi Iwai }
844352f7f91STakashi Iwai 
845352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
846352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
847352f7f91STakashi Iwai {
848352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
849352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
850352f7f91STakashi Iwai }
851352f7f91STakashi Iwai 
852247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
853247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
854247d85eeSTakashi Iwai {
855247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
856247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
857247d85eeSTakashi Iwai }
858247d85eeSTakashi Iwai 
859352f7f91STakashi Iwai static const char * const channel_name[4] = {
860352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
861352f7f91STakashi Iwai };
862352f7f91STakashi Iwai 
863352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
864247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
865247d85eeSTakashi Iwai 				    int *index, int ctl_type)
866352f7f91STakashi Iwai {
867247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
868352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
869352f7f91STakashi Iwai 
870352f7f91STakashi Iwai 	*index = 0;
871352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
872247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
873352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
874352f7f91STakashi Iwai 
875352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
876352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
877352f7f91STakashi Iwai 	 */
878352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
879352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
880352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
881352f7f91STakashi Iwai 
882247d85eeSTakashi Iwai 	/* multi-io channels */
883247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
884247d85eeSTakashi Iwai 		return channel_name[ch];
885247d85eeSTakashi Iwai 
886352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
887352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
888247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
889247d85eeSTakashi Iwai 		 * don't name it as Speaker
890247d85eeSTakashi Iwai 		 */
891247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
892247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
893247d85eeSTakashi Iwai 			break;
894352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
895352f7f91STakashi Iwai 			return "Speaker";
896352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
897352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
898352f7f91STakashi Iwai 		break;
899352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
900247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
901247d85eeSTakashi Iwai 		 * don't name it as Headphone
902247d85eeSTakashi Iwai 		 */
903247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
904247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
905247d85eeSTakashi Iwai 			break;
906352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
907352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
908352f7f91STakashi Iwai 			break;
909352f7f91STakashi Iwai 		*index = ch;
910352f7f91STakashi Iwai 		return "Headphone";
911247d85eeSTakashi Iwai 	}
912247d85eeSTakashi Iwai 
913247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
914352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
915352f7f91STakashi Iwai 		return "PCM";
916247d85eeSTakashi Iwai 
917352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
918352f7f91STakashi Iwai 		snd_BUG();
919352f7f91STakashi Iwai 		return "PCM";
920352f7f91STakashi Iwai 	}
921352f7f91STakashi Iwai 
922352f7f91STakashi Iwai 	return channel_name[ch];
923352f7f91STakashi Iwai }
924352f7f91STakashi Iwai 
925352f7f91STakashi Iwai /*
926352f7f91STakashi Iwai  * Parse output paths
927352f7f91STakashi Iwai  */
928352f7f91STakashi Iwai 
929352f7f91STakashi Iwai /* badness definition */
930352f7f91STakashi Iwai enum {
931352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
932352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
933352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
934352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
935352f7f91STakashi Iwai 	/* No possible multi-ios */
936352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
937352f7f91STakashi Iwai 	/* No individual DAC for extra output */
938352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
939352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
940352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
941352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
942352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
943352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
944352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
945352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
946352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
947352f7f91STakashi Iwai 	/* Volume widget is shared */
948352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
949352f7f91STakashi Iwai };
950352f7f91STakashi Iwai 
9510e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
952352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
953352f7f91STakashi Iwai  *
954352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
955352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
956352f7f91STakashi Iwai  * total badness for both volume and mute controls.
957352f7f91STakashi Iwai  */
9580e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
959352f7f91STakashi Iwai {
960352f7f91STakashi Iwai 	hda_nid_t nid;
961352f7f91STakashi Iwai 	unsigned int val;
962352f7f91STakashi Iwai 	int badness = 0;
963352f7f91STakashi Iwai 
964352f7f91STakashi Iwai 	if (!path)
965352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
9660e614dd0STakashi Iwai 
9670e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
9680e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
9690e614dd0STakashi Iwai 		return 0; /* already evaluated */
9700e614dd0STakashi Iwai 
971352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
972352f7f91STakashi Iwai 	if (nid) {
973352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
974352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
975352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
976352f7f91STakashi Iwai 		else
977352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
978352f7f91STakashi Iwai 	} else
979352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
980352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
981352f7f91STakashi Iwai 	if (nid) {
982352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
983352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
984352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
985352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
986352f7f91STakashi Iwai 		else
987352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
988352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
989352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
990352f7f91STakashi Iwai 		else
991352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
992352f7f91STakashi Iwai 	} else
993352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
994352f7f91STakashi Iwai 	return badness;
995352f7f91STakashi Iwai }
996352f7f91STakashi Iwai 
997352f7f91STakashi Iwai struct badness_table {
998352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
999352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
1000352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
1001352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
1002352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
1003352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
1004352f7f91STakashi Iwai };
1005352f7f91STakashi Iwai 
1006352f7f91STakashi Iwai static struct badness_table main_out_badness = {
1007352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1008352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1009352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1010352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1011352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1012352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1013352f7f91STakashi Iwai };
1014352f7f91STakashi Iwai 
1015352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
1016352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1017352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1018352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1019352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1020352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1021352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1022352f7f91STakashi Iwai };
1023352f7f91STakashi Iwai 
10247385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
10257385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
10267385df61STakashi Iwai {
10277385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10287385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
10297385df61STakashi Iwai 
10307385df61STakashi Iwai 	if (cfg->line_outs > idx)
10317385df61STakashi Iwai 		return spec->private_dac_nids[idx];
10327385df61STakashi Iwai 	idx -= cfg->line_outs;
10337385df61STakashi Iwai 	if (spec->multi_ios > idx)
10347385df61STakashi Iwai 		return spec->multi_io[idx].dac;
10357385df61STakashi Iwai 	return 0;
10367385df61STakashi Iwai }
10377385df61STakashi Iwai 
10387385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
10397385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
10407385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
10417385df61STakashi Iwai {
10427385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
10437385df61STakashi Iwai }
10447385df61STakashi Iwai 
1045352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1046352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1047352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1048196c1766STakashi Iwai 			   int *path_idx,
1049352f7f91STakashi Iwai 			   const struct badness_table *bad)
1050352f7f91STakashi Iwai {
1051352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1052352f7f91STakashi Iwai 	int i, j;
1053352f7f91STakashi Iwai 	int badness = 0;
1054352f7f91STakashi Iwai 	hda_nid_t dac;
1055352f7f91STakashi Iwai 
1056352f7f91STakashi Iwai 	if (!num_outs)
1057352f7f91STakashi Iwai 		return 0;
1058352f7f91STakashi Iwai 
1059352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
10600c8c0f56STakashi Iwai 		struct nid_path *path;
1061352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
10621e0b5286STakashi Iwai 
10630e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
10640e614dd0STakashi Iwai 		if (path) {
10650e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
10661e0b5286STakashi Iwai 			continue;
10671e0b5286STakashi Iwai 		}
10681e0b5286STakashi Iwai 
1069352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1070352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1071980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1072352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1073352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1074352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1075352f7f91STakashi Iwai 					dacs[j] = 0;
1076980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1077196c1766STakashi Iwai 					path_idx[j] = 0;
1078352f7f91STakashi Iwai 					break;
1079352f7f91STakashi Iwai 				}
1080352f7f91STakashi Iwai 			}
1081352f7f91STakashi Iwai 		}
1082352f7f91STakashi Iwai 		dac = dacs[i];
1083352f7f91STakashi Iwai 		if (!dac) {
10847385df61STakashi Iwai 			if (num_outs > 2)
10857385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
10867385df61STakashi Iwai 			if (!dac)
10877385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
10887385df61STakashi Iwai 			if (!dac)
10897385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1090352f7f91STakashi Iwai 			if (dac) {
1091352f7f91STakashi Iwai 				if (!i)
1092352f7f91STakashi Iwai 					badness += bad->shared_primary;
1093352f7f91STakashi Iwai 				else if (i == 1)
1094352f7f91STakashi Iwai 					badness += bad->shared_surr;
1095352f7f91STakashi Iwai 				else
1096352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1097352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1098352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1099352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1100352f7f91STakashi Iwai 			} else if (!i)
1101352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1102352f7f91STakashi Iwai 			else
1103352f7f91STakashi Iwai 				badness += bad->no_dac;
1104352f7f91STakashi Iwai 		}
11053ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1106117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1107b3a8c745STakashi Iwai 			/* try with aamix */
11083ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1109b3a8c745STakashi Iwai 		}
11100c8c0f56STakashi Iwai 		if (!path)
1111352f7f91STakashi Iwai 			dac = dacs[i] = 0;
1112e1284af7STakashi Iwai 		else {
11130c8c0f56STakashi Iwai 			print_nid_path("output", path);
1114e1284af7STakashi Iwai 			path->active = true;
1115196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
11160e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1117e1284af7STakashi Iwai 		}
1118352f7f91STakashi Iwai 	}
1119352f7f91STakashi Iwai 
1120352f7f91STakashi Iwai 	return badness;
1121352f7f91STakashi Iwai }
1122352f7f91STakashi Iwai 
1123352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1124352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1125352f7f91STakashi Iwai {
1126352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1127352f7f91STakashi Iwai 	int i;
1128352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1129352f7f91STakashi Iwai 
1130352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1131352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1132352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1133352f7f91STakashi Iwai 			continue;
1134352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1135352f7f91STakashi Iwai 			if (nid_found)
1136352f7f91STakashi Iwai 				return 0;
1137352f7f91STakashi Iwai 			nid_found = nid;
1138352f7f91STakashi Iwai 		}
1139352f7f91STakashi Iwai 	}
1140352f7f91STakashi Iwai 	return nid_found;
1141352f7f91STakashi Iwai }
1142352f7f91STakashi Iwai 
1143352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1144352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1145352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1146352f7f91STakashi Iwai {
1147352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1148352f7f91STakashi Iwai 
1149352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1150352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1151352f7f91STakashi Iwai 		return false;
1152352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1153352f7f91STakashi Iwai 		return false;
1154352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1155352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1156352f7f91STakashi Iwai 		return false;
1157352f7f91STakashi Iwai 	return true;
1158352f7f91STakashi Iwai }
1159352f7f91STakashi Iwai 
1160e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1161e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1162e22aab7dSTakashi Iwai {
1163e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1164e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1165e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1166e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1167e22aab7dSTakashi Iwai 	int type, i;
1168e22aab7dSTakashi Iwai 	int num_pins = 0;
1169e22aab7dSTakashi Iwai 
1170e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1171e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1172e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1173e22aab7dSTakashi Iwai 				continue;
1174e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1175e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1176e22aab7dSTakashi Iwai 				num_pins++;
1177e22aab7dSTakashi Iwai 		}
1178e22aab7dSTakashi Iwai 	}
1179e22aab7dSTakashi Iwai 	return num_pins;
1180e22aab7dSTakashi Iwai }
1181e22aab7dSTakashi Iwai 
1182352f7f91STakashi Iwai /*
1183352f7f91STakashi Iwai  * multi-io helper
1184352f7f91STakashi Iwai  *
1185352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1186352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1187352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1188352f7f91STakashi Iwai  * the badness value.
1189352f7f91STakashi Iwai  */
1190352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1191352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1192e22aab7dSTakashi Iwai 			  bool hardwired)
1193352f7f91STakashi Iwai {
1194352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1195352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1196e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1197352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1198352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1199352f7f91STakashi Iwai 	int badness = 0;
12000e614dd0STakashi Iwai 	struct nid_path *path;
1201352f7f91STakashi Iwai 
1202352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1203352f7f91STakashi Iwai 	if (old_pins >= 2)
1204352f7f91STakashi Iwai 		goto end_fill;
1205352f7f91STakashi Iwai 
1206e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1207352f7f91STakashi Iwai 	if (num_pins < 2)
1208352f7f91STakashi Iwai 		goto end_fill;
1209352f7f91STakashi Iwai 
1210352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1211352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1212352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1213352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1214352f7f91STakashi Iwai 
1215352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1216352f7f91STakashi Iwai 				continue;
1217352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1218352f7f91STakashi Iwai 				continue;
1219352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1220352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1221352f7f91STakashi Iwai 					break;
1222352f7f91STakashi Iwai 			}
1223352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1224352f7f91STakashi Iwai 				continue;
1225352f7f91STakashi Iwai 
1226352f7f91STakashi Iwai 			if (hardwired)
1227352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1228352f7f91STakashi Iwai 			else if (!dac)
1229352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1230352f7f91STakashi Iwai 			if (!dac) {
1231352f7f91STakashi Iwai 				badness++;
1232352f7f91STakashi Iwai 				continue;
1233352f7f91STakashi Iwai 			}
12343ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
12353ca529d3STakashi Iwai 						    -spec->mixer_nid);
12360c8c0f56STakashi Iwai 			if (!path) {
1237352f7f91STakashi Iwai 				badness++;
1238352f7f91STakashi Iwai 				continue;
1239352f7f91STakashi Iwai 			}
12400c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1241352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1242352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1243196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1244196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1245352f7f91STakashi Iwai 			spec->multi_ios++;
1246352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1247352f7f91STakashi Iwai 				break;
1248352f7f91STakashi Iwai 		}
1249352f7f91STakashi Iwai 	}
1250352f7f91STakashi Iwai  end_fill:
1251352f7f91STakashi Iwai 	if (badness)
1252352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1253352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1254352f7f91STakashi Iwai 		if (hardwired)
1255352f7f91STakashi Iwai 			return 1; /* nothing found */
1256352f7f91STakashi Iwai 		else
1257352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1258352f7f91STakashi Iwai 	}
1259352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1260352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1261352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1262352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1263352f7f91STakashi Iwai 		return badness;
1264352f7f91STakashi Iwai 	}
1265352f7f91STakashi Iwai 
1266352f7f91STakashi Iwai 	/* assign volume and mute controls */
12670e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
12680e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
12690e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
12700e614dd0STakashi Iwai 	}
1271352f7f91STakashi Iwai 
1272352f7f91STakashi Iwai 	return badness;
1273352f7f91STakashi Iwai }
1274352f7f91STakashi Iwai 
1275352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1276352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1277196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1278352f7f91STakashi Iwai {
1279b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1280352f7f91STakashi Iwai 	int i;
1281352f7f91STakashi Iwai 	bool found = false;
1282352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
12830c8c0f56STakashi Iwai 		struct nid_path *path;
1284352f7f91STakashi Iwai 		hda_nid_t dac;
1285352f7f91STakashi Iwai 		if (dacs[i])
1286352f7f91STakashi Iwai 			continue;
1287352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1288352f7f91STakashi Iwai 		if (!dac)
1289352f7f91STakashi Iwai 			continue;
12903ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
12913ca529d3STakashi Iwai 					    -spec->mixer_nid);
1292117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
12933ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
12940c8c0f56STakashi Iwai 		if (path) {
1295352f7f91STakashi Iwai 			dacs[i] = dac;
1296352f7f91STakashi Iwai 			found = true;
12970c8c0f56STakashi Iwai 			print_nid_path("output", path);
1298e1284af7STakashi Iwai 			path->active = true;
1299196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1300352f7f91STakashi Iwai 		}
1301352f7f91STakashi Iwai 	}
1302352f7f91STakashi Iwai 	return found;
1303352f7f91STakashi Iwai }
1304352f7f91STakashi Iwai 
1305c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1306c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1307c30aa7b2STakashi Iwai {
13083ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1309c30aa7b2STakashi Iwai 	struct nid_path *path;
1310c30aa7b2STakashi Iwai 
1311c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
13123ca529d3STakashi Iwai 	if (!path || !path->depth ||
13133ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1314c30aa7b2STakashi Iwai 		return 0;
1315c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1316c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
13173ca529d3STakashi Iwai 				    spec->mixer_nid);
1318c30aa7b2STakashi Iwai 	if (!path)
1319c30aa7b2STakashi Iwai 		return 0;
1320c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1321c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1322c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1323c30aa7b2STakashi Iwai }
1324c30aa7b2STakashi Iwai 
1325a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1326a07a949bSTakashi Iwai  * shared dac pointed by the paths
1327a07a949bSTakashi Iwai  */
1328a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1329a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1330a07a949bSTakashi Iwai {
1331a07a949bSTakashi Iwai 	struct nid_path *path;
1332a07a949bSTakashi Iwai 	int i;
1333a07a949bSTakashi Iwai 
1334a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1335a07a949bSTakashi Iwai 		if (dacs[i])
1336a07a949bSTakashi Iwai 			continue;
1337a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1338a07a949bSTakashi Iwai 		if (!path)
1339a07a949bSTakashi Iwai 			continue;
1340a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1341a07a949bSTakashi Iwai 	}
1342a07a949bSTakashi Iwai }
1343a07a949bSTakashi Iwai 
1344352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1345352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1346352f7f91STakashi Iwai 			      bool fill_hardwired,
1347352f7f91STakashi Iwai 			      bool fill_mio_first)
1348352f7f91STakashi Iwai {
1349352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1350352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1351352f7f91STakashi Iwai 	int i, err, badness;
1352ea46c3c8STakashi Iwai 	unsigned int val;
1353352f7f91STakashi Iwai 
1354352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1355352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1356352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1357352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1358352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1359352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1360352f7f91STakashi Iwai 	spec->multi_ios = 0;
1361352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1362cd5be3f9STakashi Iwai 
1363cd5be3f9STakashi Iwai 	/* clear path indices */
1364cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1365cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1366cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1367cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1368cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1369c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1370cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1371cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1372cd5be3f9STakashi Iwai 
1373352f7f91STakashi Iwai 	badness = 0;
1374352f7f91STakashi Iwai 
1375352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1376352f7f91STakashi Iwai 	if (fill_hardwired) {
1377352f7f91STakashi Iwai 		bool mapped;
1378352f7f91STakashi Iwai 		do {
1379352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1380352f7f91STakashi Iwai 					     cfg->line_out_pins,
1381196c1766STakashi Iwai 					     spec->private_dac_nids,
1382196c1766STakashi Iwai 					     spec->out_paths);
1383352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1384352f7f91STakashi Iwai 					      cfg->hp_pins,
1385196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1386196c1766STakashi Iwai 					      spec->hp_paths);
1387352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1388352f7f91STakashi Iwai 					      cfg->speaker_pins,
1389196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1390196c1766STakashi Iwai 					      spec->speaker_paths);
1391352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1392352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1393e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1394352f7f91STakashi Iwai 				if (!err)
1395352f7f91STakashi Iwai 					mapped = true;
1396352f7f91STakashi Iwai 			}
1397352f7f91STakashi Iwai 		} while (mapped);
1398352f7f91STakashi Iwai 	}
1399352f7f91STakashi Iwai 
1400352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1401196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1402352f7f91STakashi Iwai 				   &main_out_badness);
1403352f7f91STakashi Iwai 
1404352f7f91STakashi Iwai 	if (fill_mio_first &&
1405352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1406352f7f91STakashi Iwai 		/* try to fill multi-io first */
1407e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1408352f7f91STakashi Iwai 		if (err < 0)
1409352f7f91STakashi Iwai 			return err;
1410352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1411352f7f91STakashi Iwai 	}
1412352f7f91STakashi Iwai 
1413352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1414352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1415352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1416196c1766STakashi Iwai 				      spec->hp_paths,
1417352f7f91STakashi Iwai 				      &extra_out_badness);
1418352f7f91STakashi Iwai 		if (err < 0)
1419352f7f91STakashi Iwai 			return err;
1420352f7f91STakashi Iwai 		badness += err;
1421352f7f91STakashi Iwai 	}
1422352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1423352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1424352f7f91STakashi Iwai 				      cfg->speaker_pins,
1425352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1426196c1766STakashi Iwai 				      spec->speaker_paths,
1427352f7f91STakashi Iwai 				      &extra_out_badness);
1428352f7f91STakashi Iwai 		if (err < 0)
1429352f7f91STakashi Iwai 			return err;
1430352f7f91STakashi Iwai 		badness += err;
1431352f7f91STakashi Iwai 	}
1432352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1433e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1434352f7f91STakashi Iwai 		if (err < 0)
1435352f7f91STakashi Iwai 			return err;
1436352f7f91STakashi Iwai 		badness += err;
1437352f7f91STakashi Iwai 	}
1438e22aab7dSTakashi Iwai 
1439c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1440c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1441c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1442c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1443c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1444c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1445c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1446c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1447c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1448c30aa7b2STakashi Iwai 	}
1449c30aa7b2STakashi Iwai 
1450e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1451e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1452e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1453352f7f91STakashi Iwai 
1454a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1455a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1456a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1457a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1458a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1459a07a949bSTakashi Iwai 		else {
1460a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1461a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1462a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1463a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1464a07a949bSTakashi Iwai 		}
1465a07a949bSTakashi Iwai 	}
1466a07a949bSTakashi Iwai 
1467a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1468c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1469a07a949bSTakashi Iwai 
1470352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1471352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1472352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1473352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1474352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1475352f7f91STakashi Iwai 		spec->multi_ios = 0;
1476352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1477352f7f91STakashi Iwai 	}
1478352f7f91STakashi Iwai 
1479a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1480a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1481a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1482a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1483a07a949bSTakashi Iwai 				   spec->hp_paths);
1484a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1485a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1486a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1487a07a949bSTakashi Iwai 				   spec->speaker_paths);
1488a07a949bSTakashi Iwai 
14892c12c30dSTakashi Iwai 	/* set initial pinctl targets */
1490ea46c3c8STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
1491ea46c3c8STakashi Iwai 		val = PIN_HP;
1492ea46c3c8STakashi Iwai 	else
1493ea46c3c8STakashi Iwai 		val = PIN_OUT;
1494ea46c3c8STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
14952c12c30dSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
14962c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
1497ea46c3c8STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1498ea46c3c8STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
14992c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
1500ea46c3c8STakashi Iwai 				cfg->speaker_pins, val);
1501ea46c3c8STakashi Iwai 	}
15022c12c30dSTakashi Iwai 
1503352f7f91STakashi Iwai 	return badness;
1504352f7f91STakashi Iwai }
1505352f7f91STakashi Iwai 
1506352f7f91STakashi Iwai #define DEBUG_BADNESS
1507352f7f91STakashi Iwai 
1508352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1509352f7f91STakashi Iwai #define debug_badness	snd_printdd
1510352f7f91STakashi Iwai #else
1511352f7f91STakashi Iwai #define debug_badness(...)
1512352f7f91STakashi Iwai #endif
1513352f7f91STakashi Iwai 
1514352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1515352f7f91STakashi Iwai {
1516352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1517352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1518708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1519352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1520352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1521352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1522352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1523352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1524352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1525352f7f91STakashi Iwai 			      spec->multi_ios,
1526352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1527352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1528352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1529352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1530708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1531352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1532352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1533352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1534352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1535352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1536352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1537352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1538352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1539352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1540352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1541352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1542352f7f91STakashi Iwai }
1543352f7f91STakashi Iwai 
1544352f7f91STakashi Iwai /* find all available DACs of the codec */
1545352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1546352f7f91STakashi Iwai {
1547352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1548352f7f91STakashi Iwai 	int i;
1549352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1550352f7f91STakashi Iwai 
1551352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1552352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1553352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1554352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1555352f7f91STakashi Iwai 			continue;
1556352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1557352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1558352f7f91STakashi Iwai 			break;
1559352f7f91STakashi Iwai 		}
1560352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1561352f7f91STakashi Iwai 	}
1562352f7f91STakashi Iwai }
1563352f7f91STakashi Iwai 
1564352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1565352f7f91STakashi Iwai {
1566352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1567352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1568352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1569352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1570352f7f91STakashi Iwai 	int badness;
1571352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1572352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1573352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1574352f7f91STakashi Iwai 
1575352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1576352f7f91STakashi Iwai 	if (!best_cfg)
1577352f7f91STakashi Iwai 		return -ENOMEM;
1578352f7f91STakashi Iwai 	*best_cfg = *cfg;
1579352f7f91STakashi Iwai 
1580352f7f91STakashi Iwai 	for (;;) {
1581352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1582352f7f91STakashi Iwai 					     fill_mio_first);
1583352f7f91STakashi Iwai 		if (badness < 0) {
1584352f7f91STakashi Iwai 			kfree(best_cfg);
1585352f7f91STakashi Iwai 			return badness;
1586352f7f91STakashi Iwai 		}
1587352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1588352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1589352f7f91STakashi Iwai 			      badness);
1590352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1591352f7f91STakashi Iwai 		if (badness < best_badness) {
1592352f7f91STakashi Iwai 			best_badness = badness;
1593352f7f91STakashi Iwai 			*best_cfg = *cfg;
1594352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1595352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1596352f7f91STakashi Iwai 		}
1597352f7f91STakashi Iwai 		if (!badness)
1598352f7f91STakashi Iwai 			break;
1599352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1600352f7f91STakashi Iwai 		if (!fill_mio_first)
1601352f7f91STakashi Iwai 			continue;
1602352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1603352f7f91STakashi Iwai 		if (!fill_hardwired)
1604352f7f91STakashi Iwai 			continue;
1605352f7f91STakashi Iwai 		if (hp_spk_swapped)
1606352f7f91STakashi Iwai 			break;
1607352f7f91STakashi Iwai 		hp_spk_swapped = true;
1608352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1609352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1610352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1611352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1612352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1613352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1614352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1615352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1616352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1617352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1618352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1619352f7f91STakashi Iwai 			fill_hardwired = true;
1620352f7f91STakashi Iwai 			continue;
1621352f7f91STakashi Iwai 		}
1622352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1623352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1624352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1625352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1626352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1627352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1628352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1629352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1630352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1631352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1632352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1633352f7f91STakashi Iwai 			fill_hardwired = true;
1634352f7f91STakashi Iwai 			continue;
1635352f7f91STakashi Iwai 		}
1636352f7f91STakashi Iwai 		break;
1637352f7f91STakashi Iwai 	}
1638352f7f91STakashi Iwai 
1639352f7f91STakashi Iwai 	if (badness) {
16400c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1641352f7f91STakashi Iwai 		*cfg = *best_cfg;
1642352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1643352f7f91STakashi Iwai 	}
1644352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1645352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1646352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1647352f7f91STakashi Iwai 
1648352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1649352f7f91STakashi Iwai 		struct nid_path *path;
1650196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1651352f7f91STakashi Iwai 		if (path)
1652352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
16537a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
16547a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
16557a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1656352f7f91STakashi Iwai 	}
1657352f7f91STakashi Iwai 
1658352f7f91STakashi Iwai 	kfree(best_cfg);
1659352f7f91STakashi Iwai 	return 0;
1660352f7f91STakashi Iwai }
1661352f7f91STakashi Iwai 
1662352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1663352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1664352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1665352f7f91STakashi Iwai {
1666352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1667352f7f91STakashi Iwai 	int i, err, noutputs;
1668352f7f91STakashi Iwai 
1669352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1670352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1671352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1672352f7f91STakashi Iwai 
1673352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1674352f7f91STakashi Iwai 		const char *name;
1675352f7f91STakashi Iwai 		int index;
1676352f7f91STakashi Iwai 		struct nid_path *path;
1677352f7f91STakashi Iwai 
1678196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1679352f7f91STakashi Iwai 		if (!path)
1680352f7f91STakashi Iwai 			continue;
1681247d85eeSTakashi Iwai 
1682247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1683352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1684352f7f91STakashi Iwai 			/* Center/LFE */
1685352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1686352f7f91STakashi Iwai 			if (err < 0)
1687352f7f91STakashi Iwai 				return err;
1688352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1689352f7f91STakashi Iwai 			if (err < 0)
1690352f7f91STakashi Iwai 				return err;
1691247d85eeSTakashi Iwai 		} else {
1692247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1693247d85eeSTakashi Iwai 			if (err < 0)
1694247d85eeSTakashi Iwai 				return err;
1695247d85eeSTakashi Iwai 		}
1696247d85eeSTakashi Iwai 
1697247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1698247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1699352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1700352f7f91STakashi Iwai 			if (err < 0)
1701352f7f91STakashi Iwai 				return err;
1702352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1703352f7f91STakashi Iwai 			if (err < 0)
1704352f7f91STakashi Iwai 				return err;
1705352f7f91STakashi Iwai 		} else {
1706352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1707352f7f91STakashi Iwai 			if (err < 0)
1708352f7f91STakashi Iwai 				return err;
1709352f7f91STakashi Iwai 		}
1710352f7f91STakashi Iwai 	}
1711352f7f91STakashi Iwai 	return 0;
1712352f7f91STakashi Iwai }
1713352f7f91STakashi Iwai 
1714c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1715196c1766STakashi Iwai 			    const char *pfx, int cidx)
1716352f7f91STakashi Iwai {
1717352f7f91STakashi Iwai 	struct nid_path *path;
1718352f7f91STakashi Iwai 	int err;
1719352f7f91STakashi Iwai 
1720196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1721352f7f91STakashi Iwai 	if (!path)
1722352f7f91STakashi Iwai 		return 0;
1723352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1724352f7f91STakashi Iwai 	if (err < 0)
1725352f7f91STakashi Iwai 		return err;
1726352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1727352f7f91STakashi Iwai 	if (err < 0)
1728352f7f91STakashi Iwai 		return err;
1729352f7f91STakashi Iwai 	return 0;
1730352f7f91STakashi Iwai }
1731352f7f91STakashi Iwai 
1732352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1733352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1734196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1735352f7f91STakashi Iwai {
1736c2c80383STakashi Iwai 	int i;
1737352f7f91STakashi Iwai 
1738352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1739c2c80383STakashi Iwai 		const char *name;
1740c2c80383STakashi Iwai 		char tmp[44];
1741c2c80383STakashi Iwai 		int err, idx = 0;
1742c2c80383STakashi Iwai 
1743c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1744c2c80383STakashi Iwai 			name = "Bass Speaker";
1745c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1746c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1747352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1748c2c80383STakashi Iwai 			name = tmp;
1749352f7f91STakashi Iwai 		} else {
1750c2c80383STakashi Iwai 			name = pfx;
1751c2c80383STakashi Iwai 			idx = i;
1752352f7f91STakashi Iwai 		}
1753c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1754352f7f91STakashi Iwai 		if (err < 0)
1755352f7f91STakashi Iwai 			return err;
1756352f7f91STakashi Iwai 	}
1757352f7f91STakashi Iwai 	return 0;
1758352f7f91STakashi Iwai }
1759352f7f91STakashi Iwai 
1760352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1761352f7f91STakashi Iwai {
1762352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1763352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1764196c1766STakashi Iwai 				 spec->hp_paths,
1765352f7f91STakashi Iwai 				 "Headphone");
1766352f7f91STakashi Iwai }
1767352f7f91STakashi Iwai 
1768352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1769352f7f91STakashi Iwai {
1770352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1771352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1772196c1766STakashi Iwai 				 spec->speaker_paths,
1773352f7f91STakashi Iwai 				 "Speaker");
1774352f7f91STakashi Iwai }
1775352f7f91STakashi Iwai 
1776352f7f91STakashi Iwai /*
177738cf6f1aSTakashi Iwai  * independent HP controls
177838cf6f1aSTakashi Iwai  */
177938cf6f1aSTakashi Iwai 
178038cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
178138cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
178238cf6f1aSTakashi Iwai {
178338cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
178438cf6f1aSTakashi Iwai }
178538cf6f1aSTakashi Iwai 
178638cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
178738cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
178838cf6f1aSTakashi Iwai {
178938cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
179038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
179138cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
179238cf6f1aSTakashi Iwai 	return 0;
179338cf6f1aSTakashi Iwai }
179438cf6f1aSTakashi Iwai 
179538cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
179638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
179738cf6f1aSTakashi Iwai {
179838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
179938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
180038cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
180138cf6f1aSTakashi Iwai 	int ret = 0;
180238cf6f1aSTakashi Iwai 
180338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
180438cf6f1aSTakashi Iwai 	if (spec->active_streams) {
180538cf6f1aSTakashi Iwai 		ret = -EBUSY;
180638cf6f1aSTakashi Iwai 		goto unlock;
180738cf6f1aSTakashi Iwai 	}
180838cf6f1aSTakashi Iwai 
180938cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
181038cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
181138cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
181238cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
181338cf6f1aSTakashi Iwai 		else
181438cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
181538cf6f1aSTakashi Iwai 		ret = 1;
181638cf6f1aSTakashi Iwai 	}
181738cf6f1aSTakashi Iwai  unlock:
181838cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
181938cf6f1aSTakashi Iwai 	return ret;
182038cf6f1aSTakashi Iwai }
182138cf6f1aSTakashi Iwai 
182238cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
182338cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
182438cf6f1aSTakashi Iwai 	.name = "Independent HP",
182538cf6f1aSTakashi Iwai 	.info = indep_hp_info,
182638cf6f1aSTakashi Iwai 	.get = indep_hp_get,
182738cf6f1aSTakashi Iwai 	.put = indep_hp_put,
182838cf6f1aSTakashi Iwai };
182938cf6f1aSTakashi Iwai 
183038cf6f1aSTakashi Iwai 
183138cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
183238cf6f1aSTakashi Iwai {
183338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
183438cf6f1aSTakashi Iwai 
183538cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
183638cf6f1aSTakashi Iwai 		return 0;
183738cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
183838cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
183938cf6f1aSTakashi Iwai 		return 0;
184038cf6f1aSTakashi Iwai 	}
184138cf6f1aSTakashi Iwai 
184238cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
184338cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
184438cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
184538cf6f1aSTakashi Iwai 		return -ENOMEM;
184638cf6f1aSTakashi Iwai 	return 0;
184738cf6f1aSTakashi Iwai }
184838cf6f1aSTakashi Iwai 
184938cf6f1aSTakashi Iwai /*
1850352f7f91STakashi Iwai  * channel mode enum control
1851352f7f91STakashi Iwai  */
1852352f7f91STakashi Iwai 
1853352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1854352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1855352f7f91STakashi Iwai {
1856352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1857352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1858a07a949bSTakashi Iwai 	int chs;
1859352f7f91STakashi Iwai 
1860352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1861352f7f91STakashi Iwai 	uinfo->count = 1;
1862352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1863352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1864352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1865a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
1866a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
1867352f7f91STakashi Iwai 	return 0;
1868352f7f91STakashi Iwai }
1869352f7f91STakashi Iwai 
1870352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1871352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1872352f7f91STakashi Iwai {
1873352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1874352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1875a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
1876a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
1877352f7f91STakashi Iwai 	return 0;
1878352f7f91STakashi Iwai }
1879352f7f91STakashi Iwai 
1880196c1766STakashi Iwai static inline struct nid_path *
1881196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1882196c1766STakashi Iwai {
1883196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1884196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1885196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1886196c1766STakashi Iwai }
1887196c1766STakashi Iwai 
1888a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
1889a5cc2509STakashi Iwai 
1890352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1891352f7f91STakashi Iwai {
1892352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1893352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1894352f7f91STakashi Iwai 	struct nid_path *path;
1895352f7f91STakashi Iwai 
1896196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1897352f7f91STakashi Iwai 	if (!path)
1898352f7f91STakashi Iwai 		return -EINVAL;
1899352f7f91STakashi Iwai 
1900352f7f91STakashi Iwai 	if (path->active == output)
1901352f7f91STakashi Iwai 		return 0;
1902352f7f91STakashi Iwai 
1903352f7f91STakashi Iwai 	if (output) {
19042c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
1905352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1906d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1907352f7f91STakashi Iwai 	} else {
1908d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1909352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
19102c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
1911352f7f91STakashi Iwai 	}
1912a365fed9STakashi Iwai 
1913a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
1914a5cc2509STakashi Iwai 	update_automute_all(codec);
1915a365fed9STakashi Iwai 
1916352f7f91STakashi Iwai 	return 0;
1917352f7f91STakashi Iwai }
1918352f7f91STakashi Iwai 
1919352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1920352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1921352f7f91STakashi Iwai {
1922352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1923352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1924352f7f91STakashi Iwai 	int i, ch;
1925352f7f91STakashi Iwai 
1926352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1927352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1928352f7f91STakashi Iwai 		return -EINVAL;
1929a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
1930352f7f91STakashi Iwai 		return 0;
1931a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
1932352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1933352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1934352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1935352f7f91STakashi Iwai 					  spec->const_channel_count);
1936352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1937352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1938352f7f91STakashi Iwai 	return 1;
1939352f7f91STakashi Iwai }
1940352f7f91STakashi Iwai 
1941352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1942352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1943352f7f91STakashi Iwai 	.name = "Channel Mode",
1944352f7f91STakashi Iwai 	.info = ch_mode_info,
1945352f7f91STakashi Iwai 	.get = ch_mode_get,
1946352f7f91STakashi Iwai 	.put = ch_mode_put,
1947352f7f91STakashi Iwai };
1948352f7f91STakashi Iwai 
1949352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1950352f7f91STakashi Iwai {
1951352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1952352f7f91STakashi Iwai 
1953352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
195412c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1955352f7f91STakashi Iwai 			return -ENOMEM;
1956352f7f91STakashi Iwai 	}
1957352f7f91STakashi Iwai 	return 0;
1958352f7f91STakashi Iwai }
1959352f7f91STakashi Iwai 
1960352f7f91STakashi Iwai /*
1961c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1962c30aa7b2STakashi Iwai  */
1963c30aa7b2STakashi Iwai 
1964c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1965c30aa7b2STakashi Iwai 
1966c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1967c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1968c30aa7b2STakashi Iwai {
1969c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1970c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1971c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1972c30aa7b2STakashi Iwai 	return 0;
1973c30aa7b2STakashi Iwai }
1974c30aa7b2STakashi Iwai 
1975c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1976c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1977c30aa7b2STakashi Iwai {
1978c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1979c30aa7b2STakashi Iwai 
1980c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1981c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1982c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1983c30aa7b2STakashi Iwai 		return;
1984c30aa7b2STakashi Iwai 	if (do_mix) {
1985c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1986c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1987c30aa7b2STakashi Iwai 	} else {
1988c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1989c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1990c30aa7b2STakashi Iwai 	}
1991c30aa7b2STakashi Iwai }
1992c30aa7b2STakashi Iwai 
1993c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1994c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1995c30aa7b2STakashi Iwai {
1996c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1997c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1998c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
1999c30aa7b2STakashi Iwai 
2000c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2001c30aa7b2STakashi Iwai 		return 0;
2002c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2003c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2004c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
2005c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2006c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
2007c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2008c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
2009c30aa7b2STakashi Iwai 	return 1;
2010c30aa7b2STakashi Iwai }
2011c30aa7b2STakashi Iwai 
2012c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2013c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2014c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2015c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2016c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2017c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2018c30aa7b2STakashi Iwai };
2019c30aa7b2STakashi Iwai 
2020c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2021c30aa7b2STakashi Iwai {
2022c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2023c30aa7b2STakashi Iwai 
2024c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2025c30aa7b2STakashi Iwai 		return 0;
2026c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2027c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2028c30aa7b2STakashi Iwai 		return 0;
2029c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2030c30aa7b2STakashi Iwai 		return -ENOMEM;
2031c30aa7b2STakashi Iwai 	return 0;
2032c30aa7b2STakashi Iwai }
2033c30aa7b2STakashi Iwai 
2034c30aa7b2STakashi Iwai /*
2035352f7f91STakashi Iwai  * shared headphone/mic handling
2036352f7f91STakashi Iwai  */
2037352f7f91STakashi Iwai 
2038352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2039352f7f91STakashi Iwai 
2040352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2041352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
2042352f7f91STakashi Iwai {
2043352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2044352f7f91STakashi Iwai 	unsigned int val;
2045352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
2046352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
2047352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
2048352f7f91STakashi Iwai 	 */
2049352f7f91STakashi Iwai 
2050352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2051352f7f91STakashi Iwai 
2052352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
2053352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
2054352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2055352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2056352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2057352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
20587594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
20597594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
2060352f7f91STakashi Iwai 	}
2061352f7f91STakashi Iwai 
2062352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
20632c12c30dSTakashi Iwai 	set_pin_target(codec, pin, val, true);
2064352f7f91STakashi Iwai 
2065352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
2066352f7f91STakashi Iwai 	call_update_outputs(codec);
2067352f7f91STakashi Iwai }
2068352f7f91STakashi Iwai 
2069352f7f91STakashi Iwai /* create a shared input with the headphone out */
2070352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
2071352f7f91STakashi Iwai {
2072352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2073352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2074352f7f91STakashi Iwai 	unsigned int defcfg;
2075352f7f91STakashi Iwai 	hda_nid_t nid;
2076352f7f91STakashi Iwai 
2077352f7f91STakashi Iwai 	/* only one internal input pin? */
2078352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
2079352f7f91STakashi Iwai 		return 0;
2080352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2081352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2082352f7f91STakashi Iwai 		return 0;
2083352f7f91STakashi Iwai 
2084352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2085352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2086352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2087352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2088352f7f91STakashi Iwai 	else
2089352f7f91STakashi Iwai 		return 0; /* both not available */
2090352f7f91STakashi Iwai 
2091352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2092352f7f91STakashi Iwai 		return 0; /* no input */
2093352f7f91STakashi Iwai 
2094352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
2095352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
2096352f7f91STakashi Iwai 	cfg->num_inputs = 2;
2097352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
2098352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2099352f7f91STakashi Iwai 	return 0;
2100352f7f91STakashi Iwai }
2101352f7f91STakashi Iwai 
2102978e77e7STakashi Iwai /*
2103978e77e7STakashi Iwai  * output jack mode
2104978e77e7STakashi Iwai  */
2105978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2106978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2107978e77e7STakashi Iwai {
2108978e77e7STakashi Iwai 	static const char * const texts[] = {
2109978e77e7STakashi Iwai 		"Line Out", "Headphone Out",
2110978e77e7STakashi Iwai 	};
2111978e77e7STakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
2112978e77e7STakashi Iwai }
2113978e77e7STakashi Iwai 
2114978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2115978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2116978e77e7STakashi Iwai {
2117978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2118978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2119978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2120978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2121978e77e7STakashi Iwai 	else
2122978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2123978e77e7STakashi Iwai 	return 0;
2124978e77e7STakashi Iwai }
2125978e77e7STakashi Iwai 
2126978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2127978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2128978e77e7STakashi Iwai {
2129978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2130978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2131978e77e7STakashi Iwai 	unsigned int val;
2132978e77e7STakashi Iwai 
2133978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2134978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2135978e77e7STakashi Iwai 		return 0;
2136978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2137978e77e7STakashi Iwai 	return 1;
2138978e77e7STakashi Iwai }
2139978e77e7STakashi Iwai 
2140978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2141978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2142978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2143978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2144978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2145978e77e7STakashi Iwai };
2146978e77e7STakashi Iwai 
2147978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2148978e77e7STakashi Iwai {
2149978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2150978e77e7STakashi Iwai 	int i;
2151978e77e7STakashi Iwai 
2152978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2153978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2154978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2155978e77e7STakashi Iwai 			return true;
2156978e77e7STakashi Iwai 	}
2157978e77e7STakashi Iwai 	return false;
2158978e77e7STakashi Iwai }
2159978e77e7STakashi Iwai 
2160978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2161978e77e7STakashi Iwai 			       char *name, size_t name_len)
2162978e77e7STakashi Iwai {
2163978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2164978e77e7STakashi Iwai 	int idx = 0;
2165978e77e7STakashi Iwai 
2166978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2167978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2168978e77e7STakashi Iwai 
2169978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2170978e77e7STakashi Iwai 		;
2171978e77e7STakashi Iwai }
2172978e77e7STakashi Iwai 
2173978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2174978e77e7STakashi Iwai 				 hda_nid_t *pins)
2175978e77e7STakashi Iwai {
2176978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2177978e77e7STakashi Iwai 	int i;
2178978e77e7STakashi Iwai 
2179978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2180978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2181978e77e7STakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2182978e77e7STakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
2183978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2184978e77e7STakashi Iwai 			char name[44];
2185978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2186978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2187978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2188978e77e7STakashi Iwai 			if (!knew)
2189978e77e7STakashi Iwai 				return -ENOMEM;
2190978e77e7STakashi Iwai 			knew->private_value = pin;
2191978e77e7STakashi Iwai 		}
2192978e77e7STakashi Iwai 	}
2193978e77e7STakashi Iwai 
2194978e77e7STakashi Iwai 	return 0;
2195978e77e7STakashi Iwai }
2196978e77e7STakashi Iwai 
219729476558STakashi Iwai /*
219829476558STakashi Iwai  * input jack mode
219929476558STakashi Iwai  */
220029476558STakashi Iwai 
220129476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
220229476558STakashi Iwai #define NUM_VREFS	6
220329476558STakashi Iwai 
220429476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
220529476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
220629476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
220729476558STakashi Iwai };
220829476558STakashi Iwai 
220929476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
221029476558STakashi Iwai {
221129476558STakashi Iwai 	unsigned int pincap;
221229476558STakashi Iwai 
221329476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
221429476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
221529476558STakashi Iwai 	/* filter out unusual vrefs */
221629476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
221729476558STakashi Iwai 	return pincap;
221829476558STakashi Iwai }
221929476558STakashi Iwai 
222029476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
222129476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
222229476558STakashi Iwai {
222329476558STakashi Iwai 	unsigned int i, n = 0;
222429476558STakashi Iwai 
222529476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
222629476558STakashi Iwai 		if (vref_caps & (1 << i)) {
222729476558STakashi Iwai 			if (n == item_idx)
222829476558STakashi Iwai 				return i;
222929476558STakashi Iwai 			n++;
223029476558STakashi Iwai 		}
223129476558STakashi Iwai 	}
223229476558STakashi Iwai 	return 0;
223329476558STakashi Iwai }
223429476558STakashi Iwai 
223529476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
223629476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
223729476558STakashi Iwai {
223829476558STakashi Iwai 	unsigned int i, n = 0;
223929476558STakashi Iwai 
224029476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
224129476558STakashi Iwai 		if (i == idx)
224229476558STakashi Iwai 			return n;
224329476558STakashi Iwai 		if (vref_caps & (1 << i))
224429476558STakashi Iwai 			n++;
224529476558STakashi Iwai 	}
224629476558STakashi Iwai 	return 0;
224729476558STakashi Iwai }
224829476558STakashi Iwai 
224929476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
225029476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
225129476558STakashi Iwai {
225229476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
225329476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
225429476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
225529476558STakashi Iwai 
225629476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
225729476558STakashi Iwai 				 vref_texts);
225829476558STakashi Iwai 	/* set the right text */
225929476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
226029476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
226129476558STakashi Iwai 	return 0;
226229476558STakashi Iwai }
226329476558STakashi Iwai 
226429476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
226529476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
226629476558STakashi Iwai {
226729476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
226829476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
226929476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
227029476558STakashi Iwai 	unsigned int idx;
227129476558STakashi Iwai 
227229476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
227329476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
227429476558STakashi Iwai 	return 0;
227529476558STakashi Iwai }
227629476558STakashi Iwai 
227729476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
227829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
227929476558STakashi Iwai {
228029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
228129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
228229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
228329476558STakashi Iwai 	unsigned int val, idx;
228429476558STakashi Iwai 
228529476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
228629476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
228729476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
228829476558STakashi Iwai 		return 0;
228929476558STakashi Iwai 
229029476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
229129476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
229229476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
229329476558STakashi Iwai 	return 1;
229429476558STakashi Iwai }
229529476558STakashi Iwai 
229629476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
229729476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
229829476558STakashi Iwai 	.info = in_jack_mode_info,
229929476558STakashi Iwai 	.get = in_jack_mode_get,
230029476558STakashi Iwai 	.put = in_jack_mode_put,
230129476558STakashi Iwai };
230229476558STakashi Iwai 
230329476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
230429476558STakashi Iwai {
230529476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
230629476558STakashi Iwai 	unsigned int defcfg;
230729476558STakashi Iwai 	struct snd_kcontrol_new *knew;
230829476558STakashi Iwai 	char name[44];
230929476558STakashi Iwai 
231029476558STakashi Iwai 	/* no jack mode for fixed pins */
231129476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
231229476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
231329476558STakashi Iwai 		return 0;
231429476558STakashi Iwai 
231529476558STakashi Iwai 	/* no multiple vref caps? */
231629476558STakashi Iwai 	if (hweight32(get_vref_caps(codec, pin)) <= 1)
231729476558STakashi Iwai 		return 0;
231829476558STakashi Iwai 
231929476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
232029476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
232129476558STakashi Iwai 	if (!knew)
232229476558STakashi Iwai 		return -ENOMEM;
232329476558STakashi Iwai 	knew->private_value = pin;
232429476558STakashi Iwai 	return 0;
232529476558STakashi Iwai }
232629476558STakashi Iwai 
2327352f7f91STakashi Iwai 
2328352f7f91STakashi Iwai /*
2329352f7f91STakashi Iwai  * Parse input paths
2330352f7f91STakashi Iwai  */
2331352f7f91STakashi Iwai 
2332352f7f91STakashi Iwai #ifdef CONFIG_PM
2333352f7f91STakashi Iwai /* add the powersave loopback-list entry */
2334352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2335352f7f91STakashi Iwai {
2336352f7f91STakashi Iwai 	struct hda_amp_list *list;
2337352f7f91STakashi Iwai 
2338352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
2339352f7f91STakashi Iwai 		return;
2340352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
2341352f7f91STakashi Iwai 	list->nid = mix;
2342352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2343352f7f91STakashi Iwai 	list->idx = idx;
2344352f7f91STakashi Iwai 	spec->num_loopbacks++;
2345cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
2346cb53c626STakashi Iwai }
2347cb53c626STakashi Iwai #else
2348352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
2349cb53c626STakashi Iwai #endif
2350cb53c626STakashi Iwai 
2351352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2352196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2353196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2354352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
23551da177e4SLinus Torvalds {
2356352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2357352f7f91STakashi Iwai 	struct nid_path *path;
2358352f7f91STakashi Iwai 	unsigned int val;
2359352f7f91STakashi Iwai 	int err, idx;
23601da177e4SLinus Torvalds 
2361352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
2362352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
2363352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
2364352f7f91STakashi Iwai 
23653ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2366352f7f91STakashi Iwai 	if (!path)
2367352f7f91STakashi Iwai 		return -EINVAL;
23680c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2369196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2370352f7f91STakashi Iwai 
2371352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
2372352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
2373352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2374352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
2375d13bd412STakashi Iwai 		if (err < 0)
23761da177e4SLinus Torvalds 			return err;
2377352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
23781da177e4SLinus Torvalds 	}
23791da177e4SLinus Torvalds 
2380352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
2381352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2382352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
2383d13bd412STakashi Iwai 		if (err < 0)
23841da177e4SLinus Torvalds 			return err;
2385352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
23861da177e4SLinus Torvalds 	}
23871da177e4SLinus Torvalds 
2388352f7f91STakashi Iwai 	path->active = true;
2389352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
2390352f7f91STakashi Iwai 	return 0;
23911da177e4SLinus Torvalds }
23921da177e4SLinus Torvalds 
2393352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
23941da177e4SLinus Torvalds {
2395352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2396352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2397352f7f91STakashi Iwai }
2398352f7f91STakashi Iwai 
2399352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2400352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2401352f7f91STakashi Iwai {
2402352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2403352f7f91STakashi Iwai 	hda_nid_t nid;
2404352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2405352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2406352f7f91STakashi Iwai 	int i, nums = 0;
2407352f7f91STakashi Iwai 
2408352f7f91STakashi Iwai 	nid = codec->start_nid;
2409352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2410352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2411352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2412352f7f91STakashi Iwai 
2413352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2414352f7f91STakashi Iwai 			continue;
2415352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2416352f7f91STakashi Iwai 		if (++nums >= max_nums)
2417352f7f91STakashi Iwai 			break;
2418352f7f91STakashi Iwai 	}
2419352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
24200ffd534eSTakashi Iwai 
24210ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
24220ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
24230ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
24240ffd534eSTakashi Iwai 
2425352f7f91STakashi Iwai 	return nums;
2426352f7f91STakashi Iwai }
2427352f7f91STakashi Iwai 
2428352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2429352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2430352f7f91STakashi Iwai  */
2431352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2432352f7f91STakashi Iwai {
2433352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2434352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
24353a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2436352f7f91STakashi Iwai 	int i, n, nums;
2437352f7f91STakashi Iwai 
2438352f7f91STakashi Iwai  again:
2439352f7f91STakashi Iwai 	nums = 0;
24403a65bcdcSTakashi Iwai 	ok_bits = 0;
2441352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2442352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
24433a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2444352f7f91STakashi Iwai 				break;
2445352f7f91STakashi Iwai 		}
24463a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
24473a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
24483a65bcdcSTakashi Iwai 			nums++;
24493a65bcdcSTakashi Iwai 		}
2450352f7f91STakashi Iwai 	}
2451352f7f91STakashi Iwai 
24523a65bcdcSTakashi Iwai 	if (!ok_bits) {
2453352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
2454352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
2455352f7f91STakashi Iwai 			imux->num_items = 1;
2456352f7f91STakashi Iwai 			goto again;
2457352f7f91STakashi Iwai 		}
2458352f7f91STakashi Iwai 
2459352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2460352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2461352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
24623a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2463352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2464352f7f91STakashi Iwai 					break;
2465352f7f91STakashi Iwai 				}
2466352f7f91STakashi Iwai 			}
2467352f7f91STakashi Iwai 		}
2468352f7f91STakashi Iwai 
2469352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2470352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2471352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
24723a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
24733a65bcdcSTakashi Iwai 		nums = 0;
24743a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
24753a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
24763a65bcdcSTakashi Iwai 				continue;
24773a65bcdcSTakashi Iwai 			if (n != nums) {
24783a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2479980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2480980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2481980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
24823a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
24833a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
24843a65bcdcSTakashi Iwai 				}
2485980428ceSTakashi Iwai 			}
24863a65bcdcSTakashi Iwai 			nums++;
24873a65bcdcSTakashi Iwai 		}
2488352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2489352f7f91STakashi Iwai 	}
2490352f7f91STakashi Iwai 
2491352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
2492352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2493352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2494352f7f91STakashi Iwai 	}
2495352f7f91STakashi Iwai 
2496352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2497352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
2498352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
2499352f7f91STakashi Iwai 
25001da177e4SLinus Torvalds 	return 0;
25011da177e4SLinus Torvalds }
25021da177e4SLinus Torvalds 
2503f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
2504f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
25059dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
25069dba205bSTakashi Iwai 				const char *label, int anchor)
2507f3fc0b0bSTakashi Iwai {
2508f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2509f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2510f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
2511f3fc0b0bSTakashi Iwai 	bool imux_added = false;
2512f3fc0b0bSTakashi Iwai 	int c;
2513f3fc0b0bSTakashi Iwai 
2514f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
2515f3fc0b0bSTakashi Iwai 		struct nid_path *path;
2516f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
2517f3fc0b0bSTakashi Iwai 
2518f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
2519f3fc0b0bSTakashi Iwai 			continue;
2520f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
2521f3fc0b0bSTakashi Iwai 		if (!path)
2522f3fc0b0bSTakashi Iwai 			continue;
2523f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
2524f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
2525f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
2526f3fc0b0bSTakashi Iwai 
2527f3fc0b0bSTakashi Iwai 		if (!imux_added) {
2528f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
25299dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
2530f3fc0b0bSTakashi Iwai 			imux_added = true;
2531f3fc0b0bSTakashi Iwai 		}
2532f3fc0b0bSTakashi Iwai 	}
2533f3fc0b0bSTakashi Iwai 
2534f3fc0b0bSTakashi Iwai 	return 0;
2535f3fc0b0bSTakashi Iwai }
2536f3fc0b0bSTakashi Iwai 
25371da177e4SLinus Torvalds /*
2538352f7f91STakashi Iwai  * create playback/capture controls for input pins
25391da177e4SLinus Torvalds  */
25409dba205bSTakashi Iwai 
2541c970042cSTakashi Iwai /* fill the label for each input at first */
2542c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
2543c970042cSTakashi Iwai {
2544c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2545c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2546c970042cSTakashi Iwai 	int i;
2547c970042cSTakashi Iwai 
2548c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2549c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
2550c970042cSTakashi Iwai 		const char *label;
2551c970042cSTakashi Iwai 		int j, idx;
2552c970042cSTakashi Iwai 
2553c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
2554c970042cSTakashi Iwai 			continue;
2555c970042cSTakashi Iwai 
2556c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2557c970042cSTakashi Iwai 		idx = 0;
2558c970042cSTakashi Iwai 		for (j = i; j >= 0; j--) {
2559c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
2560c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
2561c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
2562c970042cSTakashi Iwai 				break;
2563c970042cSTakashi Iwai 			}
2564c970042cSTakashi Iwai 		}
2565c970042cSTakashi Iwai 
2566c970042cSTakashi Iwai 		spec->input_labels[i] = label;
2567c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
2568c970042cSTakashi Iwai 	}
2569c970042cSTakashi Iwai 
2570c970042cSTakashi Iwai 	return 0;
2571c970042cSTakashi Iwai }
2572c970042cSTakashi Iwai 
25739dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
25749dba205bSTakashi Iwai 
2575352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2576a7da6ce5STakashi Iwai {
2577352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2578352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2579352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2580352f7f91STakashi Iwai 	int num_adcs;
2581c970042cSTakashi Iwai 	int i, err;
25822c12c30dSTakashi Iwai 	unsigned int val;
2583a7da6ce5STakashi Iwai 
2584352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2585352f7f91STakashi Iwai 	if (num_adcs < 0)
2586352f7f91STakashi Iwai 		return 0;
2587352f7f91STakashi Iwai 
2588c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
2589c970042cSTakashi Iwai 	if (err < 0)
2590c970042cSTakashi Iwai 		return err;
2591c970042cSTakashi Iwai 
2592352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2593352f7f91STakashi Iwai 		hda_nid_t pin;
2594352f7f91STakashi Iwai 
2595352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2596352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2597352f7f91STakashi Iwai 			continue;
2598352f7f91STakashi Iwai 
25992c12c30dSTakashi Iwai 		val = PIN_IN;
26002c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
26012c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
26022c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, false);
26032c12c30dSTakashi Iwai 
2604352f7f91STakashi Iwai 		if (mixer) {
2605352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2606196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2607c970042cSTakashi Iwai 						       spec->input_labels[i],
2608c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
2609c970042cSTakashi Iwai 						       mixer);
2610a7da6ce5STakashi Iwai 				if (err < 0)
2611a7da6ce5STakashi Iwai 					return err;
2612a7da6ce5STakashi Iwai 			}
2613352f7f91STakashi Iwai 		}
2614352f7f91STakashi Iwai 
2615c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
2616c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
2617f3fc0b0bSTakashi Iwai 		if (err < 0)
2618f3fc0b0bSTakashi Iwai 			return err;
261929476558STakashi Iwai 
262029476558STakashi Iwai 		if (spec->add_in_jack_modes) {
262129476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
262229476558STakashi Iwai 			if (err < 0)
262329476558STakashi Iwai 				return err;
262429476558STakashi Iwai 		}
2625352f7f91STakashi Iwai 	}
2626f3fc0b0bSTakashi Iwai 
2627f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
26289dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
2629f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
2630f3fc0b0bSTakashi Iwai 		if (err < 0)
2631f3fc0b0bSTakashi Iwai 			return err;
2632352f7f91STakashi Iwai 	}
2633352f7f91STakashi Iwai 
2634a7da6ce5STakashi Iwai 	return 0;
2635a7da6ce5STakashi Iwai }
2636a7da6ce5STakashi Iwai 
26371da177e4SLinus Torvalds 
2638352f7f91STakashi Iwai /*
2639352f7f91STakashi Iwai  * input source mux
2640352f7f91STakashi Iwai  */
2641352f7f91STakashi Iwai 
2642c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
2643c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
2644352f7f91STakashi Iwai {
2645352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2646b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
2647b56fa1edSDavid Henningsson 		snd_BUG();
2648b56fa1edSDavid Henningsson 		return NULL;
2649b56fa1edSDavid Henningsson 	}
2650352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2651352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2652b56fa1edSDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_OUTS) {
2653b56fa1edSDavid Henningsson 		snd_BUG();
2654b56fa1edSDavid Henningsson 		return NULL;
2655b56fa1edSDavid Henningsson 	}
2656c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
265797ec558aSTakashi Iwai }
2658352f7f91STakashi Iwai 
2659352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2660352f7f91STakashi Iwai 		      unsigned int idx);
2661352f7f91STakashi Iwai 
2662352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2663352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2664352f7f91STakashi Iwai {
2665352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2666352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2667352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2668352f7f91STakashi Iwai }
2669352f7f91STakashi Iwai 
2670352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2671352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2672352f7f91STakashi Iwai {
2673352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2674352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2675a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2676352f7f91STakashi Iwai 
2677352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
26781da177e4SLinus Torvalds 	return 0;
26791da177e4SLinus Torvalds }
26801da177e4SLinus Torvalds 
2681352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2682352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
26831da177e4SLinus Torvalds {
2684352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2685a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2686352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2687352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2688352f7f91STakashi Iwai }
2689352f7f91STakashi Iwai 
2690352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
26911da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2692352f7f91STakashi Iwai 	.name = "Input Source",
2693352f7f91STakashi Iwai 	.info = mux_enum_info,
2694352f7f91STakashi Iwai 	.get = mux_enum_get,
2695352f7f91STakashi Iwai 	.put = mux_enum_put,
26961da177e4SLinus Torvalds };
2697071c73adSTakashi Iwai 
269847d46abbSTakashi Iwai /*
269947d46abbSTakashi Iwai  * capture volume and capture switch ctls
270047d46abbSTakashi Iwai  */
270147d46abbSTakashi Iwai 
2702352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2703352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2704071c73adSTakashi Iwai 
270547d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2706352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2707352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2708352f7f91STakashi Iwai 			  put_call_t func, int type)
2709352f7f91STakashi Iwai {
2710352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2711352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2712352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2713352f7f91STakashi Iwai 	struct nid_path *path;
2714352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2715071c73adSTakashi Iwai 
2716352f7f91STakashi Iwai 	imux = &spec->input_mux;
2717a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
2718352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
271947d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
272047d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
272147d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
272247d46abbSTakashi Iwai 	 */
2723352f7f91STakashi Iwai 	codec->cached_write = 1;
2724352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2725c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
2726c697b716STakashi Iwai 		if (!path || !path->ctls[type])
2727352f7f91STakashi Iwai 			continue;
2728352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2729352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2730352f7f91STakashi Iwai 		if (err < 0)
2731352f7f91STakashi Iwai 			goto error;
2732352f7f91STakashi Iwai 	}
2733352f7f91STakashi Iwai  error:
2734352f7f91STakashi Iwai 	codec->cached_write = 0;
2735352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
273647d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2737352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2738352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
2739352f7f91STakashi Iwai 	return err;
2740352f7f91STakashi Iwai }
2741352f7f91STakashi Iwai 
2742352f7f91STakashi Iwai /* capture volume ctl callbacks */
2743352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2744352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2745352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2746352f7f91STakashi Iwai 
2747352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2748352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2749352f7f91STakashi Iwai {
2750352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2751352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2752352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2753352f7f91STakashi Iwai }
2754352f7f91STakashi Iwai 
2755352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2756352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2757352f7f91STakashi Iwai 	.name = "Capture Volume",
2758352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2759352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2760352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2761352f7f91STakashi Iwai 	.info = cap_vol_info,
2762352f7f91STakashi Iwai 	.get = cap_vol_get,
2763352f7f91STakashi Iwai 	.put = cap_vol_put,
2764352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2765352f7f91STakashi Iwai };
2766352f7f91STakashi Iwai 
2767352f7f91STakashi Iwai /* capture switch ctl callbacks */
2768352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2769352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2770352f7f91STakashi Iwai 
2771352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2772352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2773352f7f91STakashi Iwai {
2774ae177c3fSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2775ae177c3fSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2776ae177c3fSTakashi Iwai 	int ret;
2777ae177c3fSTakashi Iwai 
2778ae177c3fSTakashi Iwai 	ret = cap_put_caller(kcontrol, ucontrol,
2779352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2780352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2781ae177c3fSTakashi Iwai 	if (ret < 0)
2782ae177c3fSTakashi Iwai 		return ret;
2783ae177c3fSTakashi Iwai 
2784ae177c3fSTakashi Iwai 	if (spec->capture_switch_hook) {
2785ae177c3fSTakashi Iwai 		bool enable = (ucontrol->value.integer.value[0] ||
2786ae177c3fSTakashi Iwai 			       ucontrol->value.integer.value[1]);
2787ae177c3fSTakashi Iwai 		spec->capture_switch_hook(codec, enable);
2788ae177c3fSTakashi Iwai 	}
2789ae177c3fSTakashi Iwai 
2790ae177c3fSTakashi Iwai 	return ret;
2791352f7f91STakashi Iwai }
2792352f7f91STakashi Iwai 
2793352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2794352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2795352f7f91STakashi Iwai 	.name = "Capture Switch",
2796352f7f91STakashi Iwai 	.info = cap_sw_info,
2797352f7f91STakashi Iwai 	.get = cap_sw_get,
2798352f7f91STakashi Iwai 	.put = cap_sw_put,
2799352f7f91STakashi Iwai };
2800352f7f91STakashi Iwai 
2801352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2802352f7f91STakashi Iwai {
2803352f7f91STakashi Iwai 	hda_nid_t nid;
2804352f7f91STakashi Iwai 	int i, depth;
2805352f7f91STakashi Iwai 
2806352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2807352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2808352f7f91STakashi Iwai 		if (depth >= path->depth)
2809352f7f91STakashi Iwai 			return -EINVAL;
2810352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2811352f7f91STakashi Iwai 		nid = path->path[i];
2812352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2813352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2814352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2815352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2816352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2817352f7f91STakashi Iwai 				int idx = path->idx[i];
2818352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2819352f7f91STakashi Iwai 					idx = 0;
2820352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2821352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2822352f7f91STakashi Iwai 			}
2823352f7f91STakashi Iwai 		}
2824352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2825352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2826352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2827352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2828352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2829352f7f91STakashi Iwai 				int idx = path->idx[i];
2830352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2831352f7f91STakashi Iwai 					idx = 0;
2832352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2833352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2834352f7f91STakashi Iwai 			}
2835352f7f91STakashi Iwai 		}
2836352f7f91STakashi Iwai 	}
2837352f7f91STakashi Iwai 	return 0;
2838352f7f91STakashi Iwai }
2839352f7f91STakashi Iwai 
2840352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2841352f7f91STakashi Iwai {
2842352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2843352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2844352f7f91STakashi Iwai 	unsigned int val;
2845352f7f91STakashi Iwai 	int i;
2846352f7f91STakashi Iwai 
2847352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2848352f7f91STakashi Iwai 		return false;
2849352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2850352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2851352f7f91STakashi Iwai 			continue;
2852352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2853352f7f91STakashi Iwai 			return false;
2854352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2855352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2856352f7f91STakashi Iwai 	}
2857352f7f91STakashi Iwai 	return false;
2858352f7f91STakashi Iwai }
2859352f7f91STakashi Iwai 
2860352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2861352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2862352f7f91STakashi Iwai 			      bool inv_dmic)
2863352f7f91STakashi Iwai {
2864352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2865352f7f91STakashi Iwai 	char tmpname[44];
2866352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2867352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2868352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2869352f7f91STakashi Iwai 	int err;
2870352f7f91STakashi Iwai 
2871352f7f91STakashi Iwai 	if (!ctl)
2872352f7f91STakashi Iwai 		return 0;
2873352f7f91STakashi Iwai 
2874352f7f91STakashi Iwai 	if (label)
2875352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2876352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2877352f7f91STakashi Iwai 	else
2878352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2879352f7f91STakashi Iwai 			 "Capture %s", sfx);
2880352f7f91STakashi Iwai 	err = add_control(spec, type, tmpname, idx,
2881352f7f91STakashi Iwai 			  amp_val_replace_channels(ctl, chs));
2882352f7f91STakashi Iwai 	if (err < 0 || !inv_dmic)
2883352f7f91STakashi Iwai 		return err;
2884352f7f91STakashi Iwai 
2885352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2886352f7f91STakashi Iwai 	if (label)
2887352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2888352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2889352f7f91STakashi Iwai 	else
2890352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2891352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2892352f7f91STakashi Iwai 	return add_control(spec, type, tmpname, idx,
2893352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2894352f7f91STakashi Iwai }
2895352f7f91STakashi Iwai 
2896352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2897352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2898352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2899352f7f91STakashi Iwai 				     bool inv_dmic)
2900352f7f91STakashi Iwai {
2901352f7f91STakashi Iwai 	int err;
2902352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2903352f7f91STakashi Iwai 	if (err < 0)
2904352f7f91STakashi Iwai 		return err;
2905352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2906071c73adSTakashi Iwai 	if (err < 0)
2907071c73adSTakashi Iwai 		return err;
2908071c73adSTakashi Iwai 	return 0;
29091da177e4SLinus Torvalds }
2910071c73adSTakashi Iwai 
2911352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2912352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2913352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2914352f7f91STakashi Iwai {
2915352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2916352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2917352f7f91STakashi Iwai 
2918352f7f91STakashi Iwai 	if (vol_ctl) {
291912c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2920352f7f91STakashi Iwai 		if (!knew)
2921352f7f91STakashi Iwai 			return -ENOMEM;
2922352f7f91STakashi Iwai 		knew->index = idx;
2923352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2924352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2925352f7f91STakashi Iwai 	}
2926352f7f91STakashi Iwai 	if (sw_ctl) {
292712c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2928352f7f91STakashi Iwai 		if (!knew)
2929352f7f91STakashi Iwai 			return -ENOMEM;
2930352f7f91STakashi Iwai 		knew->index = idx;
2931352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2932352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2933352f7f91STakashi Iwai 	}
2934352f7f91STakashi Iwai 	return 0;
2935352f7f91STakashi Iwai }
2936352f7f91STakashi Iwai 
2937352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2938352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2939352f7f91STakashi Iwai {
2940352f7f91STakashi Iwai 	struct nid_path *path;
2941352f7f91STakashi Iwai 	unsigned int ctl;
2942352f7f91STakashi Iwai 	int i;
2943352f7f91STakashi Iwai 
2944c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
2945352f7f91STakashi Iwai 	if (!path)
2946352f7f91STakashi Iwai 		return 0;
2947352f7f91STakashi Iwai 	ctl = path->ctls[type];
2948352f7f91STakashi Iwai 	if (!ctl)
2949352f7f91STakashi Iwai 		return 0;
2950352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2951c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
2952352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2953352f7f91STakashi Iwai 			return 0;
2954352f7f91STakashi Iwai 	}
2955352f7f91STakashi Iwai 	return ctl;
2956352f7f91STakashi Iwai }
2957352f7f91STakashi Iwai 
2958352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2959352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2960352f7f91STakashi Iwai {
2961352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2962352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2963c970042cSTakashi Iwai 	int i, err, type;
2964352f7f91STakashi Iwai 
2965352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2966352f7f91STakashi Iwai 		bool inv_dmic;
2967c970042cSTakashi Iwai 		int idx;
29689dba205bSTakashi Iwai 
2969c970042cSTakashi Iwai 		idx = imux->items[i].index;
2970c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
29719dba205bSTakashi Iwai 			continue;
2972352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2973352f7f91STakashi Iwai 
2974352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2975c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
2976c970042cSTakashi Iwai 						 spec->input_labels[idx],
2977c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
2978c970042cSTakashi Iwai 						 type,
2979352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2980352f7f91STakashi Iwai 						 inv_dmic);
2981d13bd412STakashi Iwai 			if (err < 0)
2982071c73adSTakashi Iwai 				return err;
2983352f7f91STakashi Iwai 		}
2984352f7f91STakashi Iwai 	}
2985071c73adSTakashi Iwai 	return 0;
2986352f7f91STakashi Iwai }
2987071c73adSTakashi Iwai 
2988352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
2989352f7f91STakashi Iwai {
2990352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2991352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2992352f7f91STakashi Iwai 	int i, n, nums, err;
2993352f7f91STakashi Iwai 
2994352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2995352f7f91STakashi Iwai 		nums = 1;
2996352f7f91STakashi Iwai 	else
2997352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
2998352f7f91STakashi Iwai 
2999352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3000352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3001624d914dSTakashi Iwai 		const char *name;
3002624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3003624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3004352f7f91STakashi Iwai 		if (!knew)
3005352f7f91STakashi Iwai 			return -ENOMEM;
3006352f7f91STakashi Iwai 		knew->count = nums;
3007352f7f91STakashi Iwai 	}
3008352f7f91STakashi Iwai 
3009352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3010352f7f91STakashi Iwai 		bool multi = false;
301199a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3012352f7f91STakashi Iwai 		bool inv_dmic = false;
3013352f7f91STakashi Iwai 		int vol, sw;
3014352f7f91STakashi Iwai 
3015352f7f91STakashi Iwai 		vol = sw = 0;
3016352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3017352f7f91STakashi Iwai 			struct nid_path *path;
3018c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3019352f7f91STakashi Iwai 			if (!path)
3020352f7f91STakashi Iwai 				continue;
3021352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3022352f7f91STakashi Iwai 			if (!vol)
3023352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
302499a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3025352f7f91STakashi Iwai 				multi = true;
302699a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
302799a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
302899a5592dSDavid Henningsson 					multi_cap_vol = true;
302999a5592dSDavid Henningsson 			}
3030352f7f91STakashi Iwai 			if (!sw)
3031352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
303299a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3033352f7f91STakashi Iwai 				multi = true;
303499a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
303599a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
303699a5592dSDavid Henningsson 					multi_cap_vol = true;
303799a5592dSDavid Henningsson 			}
3038352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3039352f7f91STakashi Iwai 				inv_dmic = true;
3040352f7f91STakashi Iwai 		}
3041352f7f91STakashi Iwai 
3042352f7f91STakashi Iwai 		if (!multi)
3043352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3044352f7f91STakashi Iwai 							inv_dmic);
304599a5592dSDavid Henningsson 		else if (!multi_cap_vol)
3046352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3047352f7f91STakashi Iwai 		else
3048352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3049d13bd412STakashi Iwai 		if (err < 0)
3050071c73adSTakashi Iwai 			return err;
3051071c73adSTakashi Iwai 	}
3052071c73adSTakashi Iwai 
30531da177e4SLinus Torvalds 	return 0;
30541da177e4SLinus Torvalds }
30551da177e4SLinus Torvalds 
3056352f7f91STakashi Iwai /*
3057352f7f91STakashi Iwai  * add mic boosts if needed
3058352f7f91STakashi Iwai  */
3059352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3060352f7f91STakashi Iwai {
3061352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3062352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3063352f7f91STakashi Iwai 	int i, err;
3064352f7f91STakashi Iwai 	hda_nid_t nid;
3065352f7f91STakashi Iwai 
3066352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3067352f7f91STakashi Iwai 		if (cfg->inputs[i].type > AUTO_PIN_MIC)
3068352f7f91STakashi Iwai 			break;
3069352f7f91STakashi Iwai 		nid = cfg->inputs[i].pin;
3070352f7f91STakashi Iwai 		if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
30715abd4888STakashi Iwai 			char boost_label[44];
3072352f7f91STakashi Iwai 			struct nid_path *path;
3073352f7f91STakashi Iwai 			unsigned int val;
3074352f7f91STakashi Iwai 
307502aba550SDavid Henningsson 			if (!nid_has_volume(codec, nid, HDA_INPUT))
307602aba550SDavid Henningsson 				continue;
307702aba550SDavid Henningsson 
3078352f7f91STakashi Iwai 			snprintf(boost_label, sizeof(boost_label),
3079c970042cSTakashi Iwai 				 "%s Boost Volume",
3080c970042cSTakashi Iwai 				 spec->input_labels[i]);
3081352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
3082352f7f91STakashi Iwai 			err = add_control(spec, HDA_CTL_WIDGET_VOL,
3083c970042cSTakashi Iwai 					  boost_label,
3084c970042cSTakashi Iwai 					  spec->input_label_idxs[i], val);
3085352f7f91STakashi Iwai 			if (err < 0)
3086352f7f91STakashi Iwai 				return err;
3087352f7f91STakashi Iwai 
3088352f7f91STakashi Iwai 			path = snd_hda_get_nid_path(codec, nid, 0);
3089352f7f91STakashi Iwai 			if (path)
3090352f7f91STakashi Iwai 				path->ctls[NID_PATH_BOOST_CTL] = val;
3091352f7f91STakashi Iwai 		}
3092352f7f91STakashi Iwai 	}
3093352f7f91STakashi Iwai 	return 0;
3094352f7f91STakashi Iwai }
3095352f7f91STakashi Iwai 
3096352f7f91STakashi Iwai /*
3097352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3098352f7f91STakashi Iwai  */
3099352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3100352f7f91STakashi Iwai {
3101352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
31020c8c0f56STakashi Iwai 	struct nid_path *path;
3103352f7f91STakashi Iwai 	int i, nums;
31042c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3105352f7f91STakashi Iwai 
3106352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3107352f7f91STakashi Iwai 	nums = 0;
3108352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
31092c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3110352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3111352f7f91STakashi Iwai 		if (!dig_nid)
3112352f7f91STakashi Iwai 			continue;
31133ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
31140c8c0f56STakashi Iwai 		if (!path)
3115352f7f91STakashi Iwai 			continue;
31160c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3117e1284af7STakashi Iwai 		path->active = true;
3118196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
31192c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3120352f7f91STakashi Iwai 		if (!nums) {
3121352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3122352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3123352f7f91STakashi Iwai 		} else {
3124352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3125352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3126352f7f91STakashi Iwai 			break;
3127352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3128352f7f91STakashi Iwai 		}
3129352f7f91STakashi Iwai 		nums++;
3130352f7f91STakashi Iwai 	}
3131352f7f91STakashi Iwai 
3132352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
31332c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3134352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3135352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3136352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3137352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3138352f7f91STakashi Iwai 				continue;
3139352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3140352f7f91STakashi Iwai 				continue;
31412c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3142352f7f91STakashi Iwai 			if (path) {
31430c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3144352f7f91STakashi Iwai 				path->active = true;
3145352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
31462430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
31472c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3148352f7f91STakashi Iwai 				break;
3149352f7f91STakashi Iwai 			}
3150352f7f91STakashi Iwai 		}
3151352f7f91STakashi Iwai 	}
3152352f7f91STakashi Iwai }
3153352f7f91STakashi Iwai 
31541da177e4SLinus Torvalds 
31551da177e4SLinus Torvalds /*
3156352f7f91STakashi Iwai  * input MUX handling
31571da177e4SLinus Torvalds  */
31581da177e4SLinus Torvalds 
3159352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3160352f7f91STakashi Iwai 
3161352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3162352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3163352f7f91STakashi Iwai 		      unsigned int idx)
3164352f7f91STakashi Iwai {
3165352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3166352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3167352f7f91STakashi Iwai 	struct nid_path *path;
3168352f7f91STakashi Iwai 
3169352f7f91STakashi Iwai 	imux = &spec->input_mux;
3170352f7f91STakashi Iwai 	if (!imux->num_items)
31711da177e4SLinus Torvalds 		return 0;
31721da177e4SLinus Torvalds 
3173352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3174352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3175352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3176352f7f91STakashi Iwai 		return 0;
3177352f7f91STakashi Iwai 
3178c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
3179352f7f91STakashi Iwai 	if (!path)
3180352f7f91STakashi Iwai 		return 0;
3181352f7f91STakashi Iwai 	if (path->active)
3182352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
3183352f7f91STakashi Iwai 
3184352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3185352f7f91STakashi Iwai 
3186352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3187352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
3188352f7f91STakashi Iwai 
3189352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3190352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3191352f7f91STakashi Iwai 
3192c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3193352f7f91STakashi Iwai 	if (!path)
3194352f7f91STakashi Iwai 		return 0;
3195352f7f91STakashi Iwai 	if (path->active)
3196352f7f91STakashi Iwai 		return 0;
3197352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3198352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3199352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
32001da177e4SLinus Torvalds 	return 1;
32011da177e4SLinus Torvalds }
32021da177e4SLinus Torvalds 
32031da177e4SLinus Torvalds 
32041da177e4SLinus Torvalds /*
3205352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
32061da177e4SLinus Torvalds  */
3207352f7f91STakashi Iwai 
3208352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3209352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
32101da177e4SLinus Torvalds {
3211352f7f91STakashi Iwai 	int i, present = 0;
32121da177e4SLinus Torvalds 
3213352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3214352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3215352f7f91STakashi Iwai 		if (!nid)
3216352f7f91STakashi Iwai 			break;
32170b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
32180b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
32190b4df931STakashi Iwai 			continue;
3220352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
32211da177e4SLinus Torvalds 	}
3222352f7f91STakashi Iwai 	return present;
32231da177e4SLinus Torvalds }
32241da177e4SLinus Torvalds 
3225352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3226352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
32272c12c30dSTakashi Iwai 			bool mute)
32281da177e4SLinus Torvalds {
3229352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3230352f7f91STakashi Iwai 	int i;
32311da177e4SLinus Torvalds 
3232352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3233352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3234352f7f91STakashi Iwai 		unsigned int val;
3235352f7f91STakashi Iwai 		if (!nid)
3236352f7f91STakashi Iwai 			break;
3237352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3238352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3239352f7f91STakashi Iwai 		 */
32402c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
32412c12c30dSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
32422c12c30dSTakashi Iwai 		else
3243352f7f91STakashi Iwai 			val = 0;
32442c12c30dSTakashi Iwai 		if (!mute)
32452c12c30dSTakashi Iwai 			val |= snd_hda_codec_get_pin_target(codec, nid);
32462c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
32472c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
32482c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
32492c12c30dSTakashi Iwai 		 * init / resume again
32502c12c30dSTakashi Iwai 		 */
32512c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3252d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3253352f7f91STakashi Iwai 	}
3254352f7f91STakashi Iwai }
32551da177e4SLinus Torvalds 
3256352f7f91STakashi Iwai /* Toggle outputs muting */
32575d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3258352f7f91STakashi Iwai {
3259352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3260352f7f91STakashi Iwai 	int on;
3261352f7f91STakashi Iwai 
3262352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3263352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3264352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3265352f7f91STakashi Iwai 	 */
3266352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
3267352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
32682c12c30dSTakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute);
3269352f7f91STakashi Iwai 
3270352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3271352f7f91STakashi Iwai 		on = 0;
3272352f7f91STakashi Iwai 	else
3273352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3274352f7f91STakashi Iwai 	on |= spec->master_mute;
327547b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3276352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
32772c12c30dSTakashi Iwai 		    spec->autocfg.speaker_pins, on);
3278352f7f91STakashi Iwai 
3279352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3280352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3281352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3282352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3283352f7f91STakashi Iwai 		return;
3284352f7f91STakashi Iwai 	if (!spec->automute_lo)
3285352f7f91STakashi Iwai 		on = 0;
3286352f7f91STakashi Iwai 	else
3287352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3288352f7f91STakashi Iwai 	on |= spec->master_mute;
328947b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3290352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
32912c12c30dSTakashi Iwai 		    spec->autocfg.line_out_pins, on);
3292352f7f91STakashi Iwai }
32935d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3294352f7f91STakashi Iwai 
3295352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3296352f7f91STakashi Iwai {
3297352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3298352f7f91STakashi Iwai 	if (spec->automute_hook)
3299352f7f91STakashi Iwai 		spec->automute_hook(codec);
3300352f7f91STakashi Iwai 	else
33015d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
3302352f7f91STakashi Iwai }
3303352f7f91STakashi Iwai 
3304352f7f91STakashi Iwai /* standard HP-automute helper */
33055d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3306352f7f91STakashi Iwai {
3307352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3308352f7f91STakashi Iwai 
3309352f7f91STakashi Iwai 	spec->hp_jack_present =
3310352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3311352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
3312352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3313352f7f91STakashi Iwai 		return;
3314352f7f91STakashi Iwai 	call_update_outputs(codec);
3315352f7f91STakashi Iwai }
33165d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3317352f7f91STakashi Iwai 
3318352f7f91STakashi Iwai /* standard line-out-automute helper */
33195d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3320352f7f91STakashi Iwai {
3321352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3322352f7f91STakashi Iwai 
3323352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3324352f7f91STakashi Iwai 		return;
3325352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3326352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3327352f7f91STakashi Iwai 		return;
3328352f7f91STakashi Iwai 
3329352f7f91STakashi Iwai 	spec->line_jack_present =
3330352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3331352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3332352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3333352f7f91STakashi Iwai 		return;
3334352f7f91STakashi Iwai 	call_update_outputs(codec);
3335352f7f91STakashi Iwai }
33365d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3337352f7f91STakashi Iwai 
3338352f7f91STakashi Iwai /* standard mic auto-switch helper */
33395d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3340352f7f91STakashi Iwai {
3341352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3342352f7f91STakashi Iwai 	int i;
3343352f7f91STakashi Iwai 
3344352f7f91STakashi Iwai 	if (!spec->auto_mic)
3345352f7f91STakashi Iwai 		return;
3346352f7f91STakashi Iwai 
3347352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
33480b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
33490b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
33500b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
33510b4df931STakashi Iwai 			continue;
33520b4df931STakashi Iwai 		if (snd_hda_jack_detect(codec, pin)) {
3353352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3354352f7f91STakashi Iwai 			return;
3355352f7f91STakashi Iwai 		}
3356352f7f91STakashi Iwai 	}
3357352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
33581da177e4SLinus Torvalds }
33595d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
33601da177e4SLinus Torvalds 
3361a5cc2509STakashi Iwai /* update jack retasking */
3362a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec)
3363a5cc2509STakashi Iwai {
3364a5cc2509STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3365a5cc2509STakashi Iwai 
3366a5cc2509STakashi Iwai 	if (spec->hp_automute_hook)
3367a5cc2509STakashi Iwai 		spec->hp_automute_hook(codec, NULL);
3368a5cc2509STakashi Iwai 	else
3369a5cc2509STakashi Iwai 		snd_hda_gen_hp_automute(codec, NULL);
3370a5cc2509STakashi Iwai 	if (spec->line_automute_hook)
3371a5cc2509STakashi Iwai 		spec->line_automute_hook(codec, NULL);
3372a5cc2509STakashi Iwai 	else
3373a5cc2509STakashi Iwai 		snd_hda_gen_line_automute(codec, NULL);
3374a5cc2509STakashi Iwai 	if (spec->mic_autoswitch_hook)
3375a5cc2509STakashi Iwai 		spec->mic_autoswitch_hook(codec, NULL);
3376a5cc2509STakashi Iwai 	else
3377a5cc2509STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, NULL);
3378a5cc2509STakashi Iwai }
3379a5cc2509STakashi Iwai 
33801da177e4SLinus Torvalds /*
3381352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
33821da177e4SLinus Torvalds  */
3383352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
3384352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
3385352f7f91STakashi Iwai {
3386352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3387352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3388352f7f91STakashi Iwai 	static const char * const texts3[] = {
3389352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
33901da177e4SLinus Torvalds 	};
33911da177e4SLinus Torvalds 
3392352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
3393352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
3394352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
3395352f7f91STakashi Iwai }
3396352f7f91STakashi Iwai 
3397352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
3398352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3399352f7f91STakashi Iwai {
3400352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3402352f7f91STakashi Iwai 	unsigned int val = 0;
3403352f7f91STakashi Iwai 	if (spec->automute_speaker)
3404352f7f91STakashi Iwai 		val++;
3405352f7f91STakashi Iwai 	if (spec->automute_lo)
3406352f7f91STakashi Iwai 		val++;
3407352f7f91STakashi Iwai 
3408352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
3409352f7f91STakashi Iwai 	return 0;
3410352f7f91STakashi Iwai }
3411352f7f91STakashi Iwai 
3412352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
3413352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3414352f7f91STakashi Iwai {
3415352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3416352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3417352f7f91STakashi Iwai 
3418352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
3419352f7f91STakashi Iwai 	case 0:
3420352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
3421352f7f91STakashi Iwai 			return 0;
3422352f7f91STakashi Iwai 		spec->automute_speaker = 0;
3423352f7f91STakashi Iwai 		spec->automute_lo = 0;
3424352f7f91STakashi Iwai 		break;
3425352f7f91STakashi Iwai 	case 1:
3426352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
3427352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
3428352f7f91STakashi Iwai 				return 0;
3429352f7f91STakashi Iwai 			spec->automute_speaker = 1;
3430352f7f91STakashi Iwai 			spec->automute_lo = 0;
3431352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
3432352f7f91STakashi Iwai 			if (spec->automute_lo)
3433352f7f91STakashi Iwai 				return 0;
3434352f7f91STakashi Iwai 			spec->automute_lo = 1;
3435352f7f91STakashi Iwai 		} else
3436352f7f91STakashi Iwai 			return -EINVAL;
3437352f7f91STakashi Iwai 		break;
3438352f7f91STakashi Iwai 	case 2:
3439352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
3440352f7f91STakashi Iwai 			return -EINVAL;
3441352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
3442352f7f91STakashi Iwai 			return 0;
3443352f7f91STakashi Iwai 		spec->automute_speaker = 1;
3444352f7f91STakashi Iwai 		spec->automute_lo = 1;
3445352f7f91STakashi Iwai 		break;
3446352f7f91STakashi Iwai 	default:
3447352f7f91STakashi Iwai 		return -EINVAL;
3448352f7f91STakashi Iwai 	}
3449352f7f91STakashi Iwai 	call_update_outputs(codec);
3450352f7f91STakashi Iwai 	return 1;
3451352f7f91STakashi Iwai }
3452352f7f91STakashi Iwai 
3453352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
3454352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3455352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
3456352f7f91STakashi Iwai 	.info = automute_mode_info,
3457352f7f91STakashi Iwai 	.get = automute_mode_get,
3458352f7f91STakashi Iwai 	.put = automute_mode_put,
3459352f7f91STakashi Iwai };
3460352f7f91STakashi Iwai 
3461352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
3462352f7f91STakashi Iwai {
3463352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3464352f7f91STakashi Iwai 
346512c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
3466352f7f91STakashi Iwai 		return -ENOMEM;
3467352f7f91STakashi Iwai 	return 0;
3468352f7f91STakashi Iwai }
3469352f7f91STakashi Iwai 
3470352f7f91STakashi Iwai /*
3471352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
3472352f7f91STakashi Iwai  * Set up appropriately if really supported
3473352f7f91STakashi Iwai  */
3474352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
3475352f7f91STakashi Iwai {
3476352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3477352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3478352f7f91STakashi Iwai 	int present = 0;
3479352f7f91STakashi Iwai 	int i, err;
3480352f7f91STakashi Iwai 
3481f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
3482f72706beSTakashi Iwai 		return 0;
3483f72706beSTakashi Iwai 
3484352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
3485352f7f91STakashi Iwai 		present++;
3486352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
3487352f7f91STakashi Iwai 		present++;
3488352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
3489352f7f91STakashi Iwai 		present++;
3490352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
3491352f7f91STakashi Iwai 		return 0;
3492352f7f91STakashi Iwai 
3493352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
3494352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
3495352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3496352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3497352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3498352f7f91STakashi Iwai 	}
3499352f7f91STakashi Iwai 
3500352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
3501352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
3502352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
3503352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
3504352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
3505352f7f91STakashi Iwai 	}
3506352f7f91STakashi Iwai 
3507352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
3508352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
3509352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
3510352f7f91STakashi Iwai 			continue;
3511352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
3512352f7f91STakashi Iwai 			    nid);
3513352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
35142e03e952STakashi Iwai 						    spec->hp_automute_hook ?
35152e03e952STakashi Iwai 						    spec->hp_automute_hook :
35165d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
3517352f7f91STakashi Iwai 		spec->detect_hp = 1;
3518352f7f91STakashi Iwai 	}
3519352f7f91STakashi Iwai 
3520352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
3521352f7f91STakashi Iwai 		if (cfg->speaker_outs)
3522352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
3523352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
3524352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
3525352f7f91STakashi Iwai 					continue;
3526352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
3527352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
3528352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
35292e03e952STakashi Iwai 								    spec->line_automute_hook ?
35302e03e952STakashi Iwai 								    spec->line_automute_hook :
35315d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
3532352f7f91STakashi Iwai 				spec->detect_lo = 1;
3533352f7f91STakashi Iwai 			}
3534352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
3535352f7f91STakashi Iwai 	}
3536352f7f91STakashi Iwai 
3537352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
3538352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
3539352f7f91STakashi Iwai 
3540352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
3541352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
3542352f7f91STakashi Iwai 
3543352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
3544352f7f91STakashi Iwai 		/* create a control for automute mode */
3545352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
3546352f7f91STakashi Iwai 		if (err < 0)
3547352f7f91STakashi Iwai 			return err;
3548352f7f91STakashi Iwai 	}
3549352f7f91STakashi Iwai 	return 0;
3550352f7f91STakashi Iwai }
3551352f7f91STakashi Iwai 
3552352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
3553352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
3554352f7f91STakashi Iwai {
3555352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3556352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3557352f7f91STakashi Iwai 	int i;
3558352f7f91STakashi Iwai 
3559352f7f91STakashi Iwai 	imux = &spec->input_mux;
3560352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
3561352f7f91STakashi Iwai 		spec->am_entry[i].idx =
3562352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
3563352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
3564352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
3565352f7f91STakashi Iwai 			return false; /* no corresponding imux */
3566352f7f91STakashi Iwai 	}
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
3569352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
3570352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
3571352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
3572352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
35732e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
35742e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
35755d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
3576352f7f91STakashi Iwai 	return true;
3577352f7f91STakashi Iwai }
3578352f7f91STakashi Iwai 
3579352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
3580352f7f91STakashi Iwai {
3581352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
3582352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
3583352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
3584352f7f91STakashi Iwai }
3585352f7f91STakashi Iwai 
3586352f7f91STakashi Iwai /*
3587352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
3588352f7f91STakashi Iwai  * Set up if really supported
3589352f7f91STakashi Iwai  */
3590352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
3591352f7f91STakashi Iwai {
3592352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3593352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3594352f7f91STakashi Iwai 	unsigned int types;
3595352f7f91STakashi Iwai 	int i, num_pins;
3596352f7f91STakashi Iwai 
3597d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
3598d12daf6fSTakashi Iwai 		return 0;
3599d12daf6fSTakashi Iwai 
3600352f7f91STakashi Iwai 	types = 0;
3601352f7f91STakashi Iwai 	num_pins = 0;
3602352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3603352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3604352f7f91STakashi Iwai 		unsigned int attr;
3605352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3606352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3607352f7f91STakashi Iwai 		if (types & (1 << attr))
3608352f7f91STakashi Iwai 			return 0; /* already occupied */
3609352f7f91STakashi Iwai 		switch (attr) {
3610352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3611352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3612352f7f91STakashi Iwai 				return 0; /* invalid type */
3613352f7f91STakashi Iwai 			break;
3614352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3615352f7f91STakashi Iwai 			return 0; /* invalid entry */
3616352f7f91STakashi Iwai 		default:
3617352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3618352f7f91STakashi Iwai 				return 0; /* invalid type */
3619352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3620352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3621352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3622352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3623352f7f91STakashi Iwai 				return 0; /* no unsol support */
3624352f7f91STakashi Iwai 			break;
3625352f7f91STakashi Iwai 		}
3626352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3627352f7f91STakashi Iwai 			return 0;
3628352f7f91STakashi Iwai 		types |= (1 << attr);
3629352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3630352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3631352f7f91STakashi Iwai 		num_pins++;
3632352f7f91STakashi Iwai 	}
3633352f7f91STakashi Iwai 
3634352f7f91STakashi Iwai 	if (num_pins < 2)
3635352f7f91STakashi Iwai 		return 0;
3636352f7f91STakashi Iwai 
3637352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3638352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3639352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3640352f7f91STakashi Iwai 	 */
3641352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3642352f7f91STakashi Iwai 	     compare_attr, NULL);
3643352f7f91STakashi Iwai 
3644352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3645352f7f91STakashi Iwai 		return 0;
3646352f7f91STakashi Iwai 
3647352f7f91STakashi Iwai 	spec->auto_mic = 1;
3648352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3649352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3650352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3651352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3652352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3653352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3654352f7f91STakashi Iwai 
3655352f7f91STakashi Iwai 	return 0;
3656352f7f91STakashi Iwai }
3657352f7f91STakashi Iwai 
3658352f7f91STakashi Iwai 
36599eb413e5STakashi Iwai /*
36609eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
36619eb413e5STakashi Iwai  *
36629eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3663352f7f91STakashi Iwai  * or a negative error code
3664352f7f91STakashi Iwai  */
3665352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
36669eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3667352f7f91STakashi Iwai {
3668352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3669352f7f91STakashi Iwai 	int err;
3670352f7f91STakashi Iwai 
36711c70a583STakashi Iwai 	parse_user_hints(codec);
36721c70a583STakashi Iwai 
36739eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
36749eb413e5STakashi Iwai 		spec->autocfg = *cfg;
36759eb413e5STakashi Iwai 		cfg = &spec->autocfg;
36769eb413e5STakashi Iwai 	}
36779eb413e5STakashi Iwai 
36786fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
36796fc4cb97SDavid Henningsson 
3680352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3681352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3682352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3683352f7f91STakashi Iwai 			spec->no_analog = 1;
3684352f7f91STakashi Iwai 			goto dig_only;
3685352f7f91STakashi Iwai 		}
3686352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3687352f7f91STakashi Iwai 	}
3688352f7f91STakashi Iwai 
3689352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3690352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3691352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3692352f7f91STakashi Iwai 		/* use HP as primary out */
3693352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3694352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3695352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3696352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3697352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3698352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3699352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3700352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3701352f7f91STakashi Iwai 	}
3702352f7f91STakashi Iwai 
3703352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3704352f7f91STakashi Iwai 	if (err < 0)
3705352f7f91STakashi Iwai 		return err;
3706352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3707352f7f91STakashi Iwai 	if (err < 0)
3708352f7f91STakashi Iwai 		return err;
3709352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3710352f7f91STakashi Iwai 	if (err < 0)
3711352f7f91STakashi Iwai 		return err;
3712352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3713352f7f91STakashi Iwai 	if (err < 0)
3714352f7f91STakashi Iwai 		return err;
3715352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3716352f7f91STakashi Iwai 	if (err < 0)
3717352f7f91STakashi Iwai 		return err;
371838cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
371938cf6f1aSTakashi Iwai 	if (err < 0)
372038cf6f1aSTakashi Iwai 		return err;
3721c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3722c30aa7b2STakashi Iwai 	if (err < 0)
3723c30aa7b2STakashi Iwai 		return err;
3724352f7f91STakashi Iwai 	err = create_shared_input(codec);
3725352f7f91STakashi Iwai 	if (err < 0)
3726352f7f91STakashi Iwai 		return err;
3727352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3728352f7f91STakashi Iwai 	if (err < 0)
3729352f7f91STakashi Iwai 		return err;
3730352f7f91STakashi Iwai 
3731a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
3732a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
3733a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
3734a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3735a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
3736a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3737a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3738a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
3739352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
3740352f7f91STakashi Iwai 					  spec->const_channel_count);
3741352f7f91STakashi Iwai 
3742352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3743352f7f91STakashi Iwai 	if (err < 0)
3744352f7f91STakashi Iwai 		return err;
3745352f7f91STakashi Iwai 
3746352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3747352f7f91STakashi Iwai 	if (err < 0)
3748352f7f91STakashi Iwai 		return err;
3749352f7f91STakashi Iwai 
3750352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3751352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3752352f7f91STakashi Iwai 		if (err < 0)
3753352f7f91STakashi Iwai 			return err;
3754352f7f91STakashi Iwai 	}
3755352f7f91STakashi Iwai 
3756352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3757352f7f91STakashi Iwai 	if (err < 0)
3758352f7f91STakashi Iwai 		return err;
3759352f7f91STakashi Iwai 
3760352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3761352f7f91STakashi Iwai 	if (err < 0)
3762352f7f91STakashi Iwai 		return err;
3763352f7f91STakashi Iwai 
3764978e77e7STakashi Iwai 	if (spec->add_out_jack_modes) {
3765978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3766978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
3767978e77e7STakashi Iwai 						    cfg->line_out_pins);
3768978e77e7STakashi Iwai 			if (err < 0)
3769978e77e7STakashi Iwai 				return err;
3770978e77e7STakashi Iwai 		}
3771978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
3772978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
3773978e77e7STakashi Iwai 						    cfg->hp_pins);
3774978e77e7STakashi Iwai 			if (err < 0)
3775978e77e7STakashi Iwai 				return err;
3776978e77e7STakashi Iwai 		}
3777978e77e7STakashi Iwai 	}
3778978e77e7STakashi Iwai 
3779352f7f91STakashi Iwai  dig_only:
3780352f7f91STakashi Iwai 	parse_digital(codec);
3781352f7f91STakashi Iwai 
3782352f7f91STakashi Iwai 	return 1;
3783352f7f91STakashi Iwai }
3784352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3785352f7f91STakashi Iwai 
3786352f7f91STakashi Iwai 
3787352f7f91STakashi Iwai /*
3788352f7f91STakashi Iwai  * Build control elements
3789352f7f91STakashi Iwai  */
3790352f7f91STakashi Iwai 
3791352f7f91STakashi Iwai /* slave controls for virtual master */
3792352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3793352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3794352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3795352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3796ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3797ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3798ee79c69aSTakashi Iwai 	"Headphone Side",
3799352f7f91STakashi Iwai 	NULL,
3800352f7f91STakashi Iwai };
3801352f7f91STakashi Iwai 
3802352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3803352f7f91STakashi Iwai {
3804352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3805352f7f91STakashi Iwai 	int err;
3806352f7f91STakashi Iwai 
380736502d02STakashi Iwai 	if (spec->kctls.used) {
3808352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3809352f7f91STakashi Iwai 		if (err < 0)
3810352f7f91STakashi Iwai 			return err;
381136502d02STakashi Iwai 	}
3812352f7f91STakashi Iwai 
3813352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3814352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3815352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3816352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3817352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3818352f7f91STakashi Iwai 		if (err < 0)
3819352f7f91STakashi Iwai 			return err;
3820352f7f91STakashi Iwai 		if (!spec->no_analog) {
3821352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3822352f7f91STakashi Iwai 							    &spec->multiout);
3823352f7f91STakashi Iwai 			if (err < 0)
3824352f7f91STakashi Iwai 				return err;
3825352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3826352f7f91STakashi Iwai 		}
3827352f7f91STakashi Iwai 	}
3828352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3829352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3830352f7f91STakashi Iwai 		if (err < 0)
3831352f7f91STakashi Iwai 			return err;
3832352f7f91STakashi Iwai 	}
3833352f7f91STakashi Iwai 
3834352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3835352f7f91STakashi Iwai 	if (!spec->no_analog &&
3836352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3837352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
38387a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
3839352f7f91STakashi Iwai 					  "Playback Volume");
3840352f7f91STakashi Iwai 		if (err < 0)
3841352f7f91STakashi Iwai 			return err;
3842352f7f91STakashi Iwai 	}
3843352f7f91STakashi Iwai 	if (!spec->no_analog &&
3844352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3845352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3846352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3847352f7f91STakashi Iwai 					    "Playback Switch",
3848352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3849352f7f91STakashi Iwai 		if (err < 0)
3850352f7f91STakashi Iwai 			return err;
3851352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3852fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3853fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3854352f7f91STakashi Iwai 	}
3855352f7f91STakashi Iwai 
3856352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3857352f7f91STakashi Iwai 
3858352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3859352f7f91STakashi Iwai 		int err;
3860352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3861352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3862352f7f91STakashi Iwai 		if (err < 0)
3863352f7f91STakashi Iwai 			return err;
3864352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3865352f7f91STakashi Iwai 		if (err < 0)
3866352f7f91STakashi Iwai 			return err;
3867352f7f91STakashi Iwai 	}
3868352f7f91STakashi Iwai 
3869352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3870352f7f91STakashi Iwai 	if (err < 0)
3871352f7f91STakashi Iwai 		return err;
3872352f7f91STakashi Iwai 
3873352f7f91STakashi Iwai 	return 0;
3874352f7f91STakashi Iwai }
3875352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3876352f7f91STakashi Iwai 
3877352f7f91STakashi Iwai 
3878352f7f91STakashi Iwai /*
3879352f7f91STakashi Iwai  * PCM definitions
3880352f7f91STakashi Iwai  */
3881352f7f91STakashi Iwai 
3882e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
3883e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
3884e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
3885e6b85f3cSTakashi Iwai 				   int action)
3886e6b85f3cSTakashi Iwai {
3887e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3888e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
3889e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
3890e6b85f3cSTakashi Iwai }
3891e6b85f3cSTakashi Iwai 
3892ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
3893ac2e8736STakashi Iwai 				  struct hda_codec *codec,
3894ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
3895ac2e8736STakashi Iwai 				  int action)
3896ac2e8736STakashi Iwai {
3897ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3898ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
3899ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
3900ac2e8736STakashi Iwai }
3901ac2e8736STakashi Iwai 
3902352f7f91STakashi Iwai /*
3903352f7f91STakashi Iwai  * Analog playback callbacks
3904352f7f91STakashi Iwai  */
3905352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3906352f7f91STakashi Iwai 			     struct hda_codec *codec,
3907352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3908352f7f91STakashi Iwai {
3909352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
391038cf6f1aSTakashi Iwai 	int err;
391138cf6f1aSTakashi Iwai 
391238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
391338cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
391438cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3915352f7f91STakashi Iwai 					     hinfo);
3916e6b85f3cSTakashi Iwai 	if (!err) {
391738cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
3918e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3919e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
3920e6b85f3cSTakashi Iwai 	}
392138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
392238cf6f1aSTakashi Iwai 	return err;
3923352f7f91STakashi Iwai }
3924352f7f91STakashi Iwai 
3925352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
392697ec558aSTakashi Iwai 				struct hda_codec *codec,
392797ec558aSTakashi Iwai 				unsigned int stream_tag,
392897ec558aSTakashi Iwai 				unsigned int format,
392997ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
393097ec558aSTakashi Iwai {
3931352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3932e6b85f3cSTakashi Iwai 	int err;
3933e6b85f3cSTakashi Iwai 
3934e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
3935352f7f91STakashi Iwai 					       stream_tag, format, substream);
3936e6b85f3cSTakashi Iwai 	if (!err)
3937e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3938e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
3939e6b85f3cSTakashi Iwai 	return err;
3940352f7f91STakashi Iwai }
394197ec558aSTakashi Iwai 
3942352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
3943352f7f91STakashi Iwai 				struct hda_codec *codec,
3944352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
3945352f7f91STakashi Iwai {
3946352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3947e6b85f3cSTakashi Iwai 	int err;
3948e6b85f3cSTakashi Iwai 
3949e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
3950e6b85f3cSTakashi Iwai 	if (!err)
3951e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3952e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
3953e6b85f3cSTakashi Iwai 	return err;
3954352f7f91STakashi Iwai }
3955352f7f91STakashi Iwai 
395638cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
395738cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
395838cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
395938cf6f1aSTakashi Iwai {
396038cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
396138cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
396238cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
3963e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
3964e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
396538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
396638cf6f1aSTakashi Iwai 	return 0;
396738cf6f1aSTakashi Iwai }
396838cf6f1aSTakashi Iwai 
3969ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
3970ac2e8736STakashi Iwai 			    struct hda_codec *codec,
3971ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
3972ac2e8736STakashi Iwai {
3973ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
3974ac2e8736STakashi Iwai 	return 0;
3975ac2e8736STakashi Iwai }
3976ac2e8736STakashi Iwai 
3977ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
3978ac2e8736STakashi Iwai 			       struct hda_codec *codec,
3979ac2e8736STakashi Iwai 			       unsigned int stream_tag,
3980ac2e8736STakashi Iwai 			       unsigned int format,
3981ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
3982ac2e8736STakashi Iwai {
3983ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
3984ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
3985ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
3986ac2e8736STakashi Iwai 	return 0;
3987ac2e8736STakashi Iwai }
3988ac2e8736STakashi Iwai 
3989ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
3990ac2e8736STakashi Iwai 			       struct hda_codec *codec,
3991ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
3992ac2e8736STakashi Iwai {
3993ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
3994ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
3995ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
3996ac2e8736STakashi Iwai 	return 0;
3997ac2e8736STakashi Iwai }
3998ac2e8736STakashi Iwai 
3999ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4000ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4001ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4002ac2e8736STakashi Iwai {
4003ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4004ac2e8736STakashi Iwai 	return 0;
4005ac2e8736STakashi Iwai }
4006ac2e8736STakashi Iwai 
400738cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
400838cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
400938cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
401038cf6f1aSTakashi Iwai {
401138cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
401238cf6f1aSTakashi Iwai 	int err = 0;
401338cf6f1aSTakashi Iwai 
401438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
401538cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
401638cf6f1aSTakashi Iwai 		err = -EBUSY;
401738cf6f1aSTakashi Iwai 	else
401838cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4019e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4020e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
402138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
402238cf6f1aSTakashi Iwai 	return err;
402338cf6f1aSTakashi Iwai }
402438cf6f1aSTakashi Iwai 
402538cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
402638cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
402738cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
402838cf6f1aSTakashi Iwai {
402938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
403038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
403138cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4032e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4033e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
403438cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
403538cf6f1aSTakashi Iwai 	return 0;
403638cf6f1aSTakashi Iwai }
403738cf6f1aSTakashi Iwai 
4038e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4039e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4040e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4041e6b85f3cSTakashi Iwai 				    unsigned int format,
4042e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4043e6b85f3cSTakashi Iwai {
4044e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4045e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4046e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4047e6b85f3cSTakashi Iwai 	return 0;
4048e6b85f3cSTakashi Iwai }
4049e6b85f3cSTakashi Iwai 
4050e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4051e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4052e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4053e6b85f3cSTakashi Iwai {
4054e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4055e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4056e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4057e6b85f3cSTakashi Iwai 	return 0;
4058e6b85f3cSTakashi Iwai }
4059e6b85f3cSTakashi Iwai 
4060352f7f91STakashi Iwai /*
4061352f7f91STakashi Iwai  * Digital out
4062352f7f91STakashi Iwai  */
4063352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4064352f7f91STakashi Iwai 				 struct hda_codec *codec,
4065352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4066352f7f91STakashi Iwai {
4067352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4068352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4069352f7f91STakashi Iwai }
4070352f7f91STakashi Iwai 
4071352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4072352f7f91STakashi Iwai 				    struct hda_codec *codec,
4073352f7f91STakashi Iwai 				    unsigned int stream_tag,
4074352f7f91STakashi Iwai 				    unsigned int format,
4075352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4076352f7f91STakashi Iwai {
4077352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4078352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4079352f7f91STakashi Iwai 					     stream_tag, format, substream);
4080352f7f91STakashi Iwai }
4081352f7f91STakashi Iwai 
4082352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4083352f7f91STakashi Iwai 				    struct hda_codec *codec,
4084352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4085352f7f91STakashi Iwai {
4086352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4087352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4088352f7f91STakashi Iwai }
4089352f7f91STakashi Iwai 
4090352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4091352f7f91STakashi Iwai 				  struct hda_codec *codec,
4092352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4093352f7f91STakashi Iwai {
4094352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4095352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4096352f7f91STakashi Iwai }
4097352f7f91STakashi Iwai 
4098352f7f91STakashi Iwai /*
4099352f7f91STakashi Iwai  * Analog capture
4100352f7f91STakashi Iwai  */
4101ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4102ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4103ac2e8736STakashi Iwai 
4104352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4105352f7f91STakashi Iwai 				   struct hda_codec *codec,
4106352f7f91STakashi Iwai 				   unsigned int stream_tag,
4107352f7f91STakashi Iwai 				   unsigned int format,
4108352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4109352f7f91STakashi Iwai {
4110352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4111352f7f91STakashi Iwai 
4112352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
411397ec558aSTakashi Iwai 				   stream_tag, 0, format);
4114ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4115ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
411697ec558aSTakashi Iwai 	return 0;
411797ec558aSTakashi Iwai }
411897ec558aSTakashi Iwai 
4119352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
412097ec558aSTakashi Iwai 				   struct hda_codec *codec,
412197ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
412297ec558aSTakashi Iwai {
4123352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
412497ec558aSTakashi Iwai 
4125352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4126352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4127ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4128ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
412997ec558aSTakashi Iwai 	return 0;
413097ec558aSTakashi Iwai }
413197ec558aSTakashi Iwai 
4132352f7f91STakashi Iwai /*
4133352f7f91STakashi Iwai  */
4134352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4135352f7f91STakashi Iwai 	.substreams = 1,
4136352f7f91STakashi Iwai 	.channels_min = 2,
4137352f7f91STakashi Iwai 	.channels_max = 8,
4138352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4139352f7f91STakashi Iwai 	.ops = {
4140352f7f91STakashi Iwai 		.open = playback_pcm_open,
414138cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4142352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4143352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4144352f7f91STakashi Iwai 	},
4145352f7f91STakashi Iwai };
4146352f7f91STakashi Iwai 
4147352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4148352f7f91STakashi Iwai 	.substreams = 1,
4149352f7f91STakashi Iwai 	.channels_min = 2,
4150352f7f91STakashi Iwai 	.channels_max = 2,
4151352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4152ac2e8736STakashi Iwai 	.ops = {
4153ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4154ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4155ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4156ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4157ac2e8736STakashi Iwai 	},
4158352f7f91STakashi Iwai };
4159352f7f91STakashi Iwai 
4160352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4161352f7f91STakashi Iwai 	.substreams = 1,
4162352f7f91STakashi Iwai 	.channels_min = 2,
4163352f7f91STakashi Iwai 	.channels_max = 2,
4164352f7f91STakashi Iwai 	/* NID is set in build_pcms */
416538cf6f1aSTakashi Iwai 	.ops = {
416638cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4167e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4168e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4169e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
417038cf6f1aSTakashi Iwai 	},
4171352f7f91STakashi Iwai };
4172352f7f91STakashi Iwai 
4173352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4174352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4175352f7f91STakashi Iwai 	.channels_min = 2,
4176352f7f91STakashi Iwai 	.channels_max = 2,
4177352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4178352f7f91STakashi Iwai 	.ops = {
4179ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4180ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4181352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4182352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4183352f7f91STakashi Iwai 	},
4184352f7f91STakashi Iwai };
4185352f7f91STakashi Iwai 
4186352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4187352f7f91STakashi Iwai 	.substreams = 1,
4188352f7f91STakashi Iwai 	.channels_min = 2,
4189352f7f91STakashi Iwai 	.channels_max = 2,
4190352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4191352f7f91STakashi Iwai 	.ops = {
4192352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4193352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4194352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4195352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4196352f7f91STakashi Iwai 	},
4197352f7f91STakashi Iwai };
4198352f7f91STakashi Iwai 
4199352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4200352f7f91STakashi Iwai 	.substreams = 1,
4201352f7f91STakashi Iwai 	.channels_min = 2,
4202352f7f91STakashi Iwai 	.channels_max = 2,
4203352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4204352f7f91STakashi Iwai };
4205352f7f91STakashi Iwai 
4206352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4207352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4208352f7f91STakashi Iwai 	.substreams = 0,
4209352f7f91STakashi Iwai 	.channels_min = 0,
4210352f7f91STakashi Iwai 	.channels_max = 0,
4211352f7f91STakashi Iwai };
4212352f7f91STakashi Iwai 
4213352f7f91STakashi Iwai /*
4214352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4215352f7f91STakashi Iwai  */
4216352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
42171da177e4SLinus Torvalds {
4218352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4219352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
42201da177e4SLinus Torvalds 
4221352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4222352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4223352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4224352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4225352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4226352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4227352f7f91STakashi Iwai 					   spec->cur_adc_format);
4228352f7f91STakashi Iwai 		return true;
4229352f7f91STakashi Iwai 	}
4230352f7f91STakashi Iwai 	return false;
4231352f7f91STakashi Iwai }
4232352f7f91STakashi Iwai 
4233352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4234352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4235352f7f91STakashi Iwai 				       struct hda_codec *codec,
4236352f7f91STakashi Iwai 				       unsigned int stream_tag,
4237352f7f91STakashi Iwai 				       unsigned int format,
4238352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4239352f7f91STakashi Iwai {
4240352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4241352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4242352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4243352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4244352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
42451da177e4SLinus Torvalds 	return 0;
42461da177e4SLinus Torvalds }
42471da177e4SLinus Torvalds 
4248352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4249352f7f91STakashi Iwai 				       struct hda_codec *codec,
4250352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4251352f7f91STakashi Iwai {
4252352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4253352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4254352f7f91STakashi Iwai 	spec->cur_adc = 0;
4255352f7f91STakashi Iwai 	return 0;
4256352f7f91STakashi Iwai }
4257352f7f91STakashi Iwai 
4258352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4259352f7f91STakashi Iwai 	.substreams = 1,
4260352f7f91STakashi Iwai 	.channels_min = 2,
4261352f7f91STakashi Iwai 	.channels_max = 2,
4262352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4263352f7f91STakashi Iwai 	.ops = {
4264352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4265352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4266352f7f91STakashi Iwai 	},
4267352f7f91STakashi Iwai };
4268352f7f91STakashi Iwai 
4269f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4270f873e536STakashi Iwai 				 const char *chip_name)
4271f873e536STakashi Iwai {
4272f873e536STakashi Iwai 	char *p;
4273f873e536STakashi Iwai 
4274f873e536STakashi Iwai 	if (*str)
4275f873e536STakashi Iwai 		return;
4276f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4277f873e536STakashi Iwai 
4278f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4279f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4280f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4281f873e536STakashi Iwai 			*p = 0;
4282f873e536STakashi Iwai 			break;
4283f873e536STakashi Iwai 		}
4284f873e536STakashi Iwai 	}
4285f873e536STakashi Iwai 	strlcat(str, sfx, len);
4286f873e536STakashi Iwai }
4287f873e536STakashi Iwai 
4288352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4289352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4290352f7f91STakashi Iwai {
4291352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4292352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4293352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4294352f7f91STakashi Iwai 	bool have_multi_adcs;
4295352f7f91STakashi Iwai 
42961da177e4SLinus Torvalds 	codec->num_pcms = 1;
42971da177e4SLinus Torvalds 	codec->pcm_info = info;
42981da177e4SLinus Torvalds 
4299352f7f91STakashi Iwai 	if (spec->no_analog)
4300352f7f91STakashi Iwai 		goto skip_analog;
4301352f7f91STakashi Iwai 
4302f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
4303f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
4304f873e536STakashi Iwai 			     " Analog", codec->chip_name);
4305352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
4306352f7f91STakashi Iwai 
4307352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
4308352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
4309352f7f91STakashi Iwai 		if (!p)
4310352f7f91STakashi Iwai 			p = &pcm_analog_playback;
4311352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4312352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4313352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
4314352f7f91STakashi Iwai 			spec->multiout.max_channels;
4315352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
4316352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
4317352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
4318352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
4319352f7f91STakashi Iwai 	}
4320352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
4321352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
4322352f7f91STakashi Iwai 		if (!p) {
4323352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
4324352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
4325352f7f91STakashi Iwai 			else
4326352f7f91STakashi Iwai 				p = &pcm_analog_capture;
4327352f7f91STakashi Iwai 		}
4328352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4329352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4330352f7f91STakashi Iwai 	}
4331352f7f91STakashi Iwai 
4332352f7f91STakashi Iwai  skip_analog:
4333352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
4334352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4335f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
4336352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
4337f873e536STakashi Iwai 				     " Digital", codec->chip_name);
4338352f7f91STakashi Iwai 		codec->num_pcms = 2;
4339352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4340352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
4341352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
4342352f7f91STakashi Iwai 		if (spec->dig_out_type)
4343352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
4344352f7f91STakashi Iwai 		else
4345352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
4346352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
4347352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
4348352f7f91STakashi Iwai 			if (!p)
4349352f7f91STakashi Iwai 				p = &pcm_digital_playback;
4350352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4351352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
4352352f7f91STakashi Iwai 		}
4353352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
4354352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
4355352f7f91STakashi Iwai 			if (!p)
4356352f7f91STakashi Iwai 				p = &pcm_digital_capture;
4357352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4358352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4359352f7f91STakashi Iwai 		}
4360352f7f91STakashi Iwai 	}
4361352f7f91STakashi Iwai 
4362352f7f91STakashi Iwai 	if (spec->no_analog)
4363352f7f91STakashi Iwai 		return 0;
4364352f7f91STakashi Iwai 
4365352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
4366352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
4367352f7f91STakashi Iwai 	 */
4368352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
4369352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
4370352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
4371352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
4372352f7f91STakashi Iwai 		codec->num_pcms = 3;
4373352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
4374352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
4375352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
4376352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
4377352f7f91STakashi Iwai 			if (!p)
4378352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
4379352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4380352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4381352f7f91STakashi Iwai 				spec->alt_dac_nid;
4382352f7f91STakashi Iwai 		} else {
4383352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4384352f7f91STakashi Iwai 				pcm_null_stream;
4385352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4386352f7f91STakashi Iwai 		}
4387352f7f91STakashi Iwai 		if (have_multi_adcs) {
4388352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
4389352f7f91STakashi Iwai 			if (!p)
4390352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
4391352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4392352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4393352f7f91STakashi Iwai 				spec->adc_nids[1];
4394352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4395352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
4396352f7f91STakashi Iwai 		} else {
4397352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4398352f7f91STakashi Iwai 				pcm_null_stream;
4399352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4400352f7f91STakashi Iwai 		}
44011da177e4SLinus Torvalds 	}
44021da177e4SLinus Torvalds 
44031da177e4SLinus Torvalds 	return 0;
44041da177e4SLinus Torvalds }
4405352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
4406352f7f91STakashi Iwai 
4407352f7f91STakashi Iwai 
4408352f7f91STakashi Iwai /*
4409352f7f91STakashi Iwai  * Standard auto-parser initializations
4410352f7f91STakashi Iwai  */
4411352f7f91STakashi Iwai 
4412d4156930STakashi Iwai /* configure the given path as a proper output */
44132c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
4414352f7f91STakashi Iwai {
4415352f7f91STakashi Iwai 	struct nid_path *path;
4416d4156930STakashi Iwai 	hda_nid_t pin;
4417352f7f91STakashi Iwai 
4418196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
4419d4156930STakashi Iwai 	if (!path || !path->depth)
4420352f7f91STakashi Iwai 		return;
4421d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
44222c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
4423e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
4424e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
4425352f7f91STakashi Iwai }
4426352f7f91STakashi Iwai 
4427352f7f91STakashi Iwai /* initialize primary output paths */
4428352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
4429352f7f91STakashi Iwai {
4430352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4431352f7f91STakashi Iwai 	int i;
4432352f7f91STakashi Iwai 
4433d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
44342c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
4435352f7f91STakashi Iwai }
4436352f7f91STakashi Iwai 
4437db23fd19STakashi Iwai 
44382c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
4439352f7f91STakashi Iwai {
4440352f7f91STakashi Iwai 	int i;
4441352f7f91STakashi Iwai 
4442d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
44432c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
4444352f7f91STakashi Iwai }
4445db23fd19STakashi Iwai 
4446db23fd19STakashi Iwai /* initialize hp and speaker paths */
4447db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
4448db23fd19STakashi Iwai {
4449db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4450db23fd19STakashi Iwai 
4451db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
44522c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
4453db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
4454db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
44552c12c30dSTakashi Iwai 				 spec->speaker_paths);
4456352f7f91STakashi Iwai }
4457352f7f91STakashi Iwai 
4458352f7f91STakashi Iwai /* initialize multi-io paths */
4459352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
4460352f7f91STakashi Iwai {
4461352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4462352f7f91STakashi Iwai 	int i;
4463352f7f91STakashi Iwai 
4464352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
4465352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
4466352f7f91STakashi Iwai 		struct nid_path *path;
4467196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
4468352f7f91STakashi Iwai 		if (!path)
4469352f7f91STakashi Iwai 			continue;
4470352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
4471352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
44722c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
4473352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
4474352f7f91STakashi Iwai 	}
4475352f7f91STakashi Iwai }
4476352f7f91STakashi Iwai 
4477352f7f91STakashi Iwai /* set up input pins and loopback paths */
4478352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
4479352f7f91STakashi Iwai {
4480352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4481352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4482352f7f91STakashi Iwai 	int i;
4483352f7f91STakashi Iwai 
4484352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4485352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4486352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
44872c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
4488352f7f91STakashi Iwai 
4489352f7f91STakashi Iwai 		/* init loopback inputs */
4490352f7f91STakashi Iwai 		if (spec->mixer_nid) {
4491352f7f91STakashi Iwai 			struct nid_path *path;
4492196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
4493352f7f91STakashi Iwai 			if (path)
4494352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
4495352f7f91STakashi Iwai 						      path->active, false);
4496352f7f91STakashi Iwai 		}
4497352f7f91STakashi Iwai 	}
4498352f7f91STakashi Iwai }
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai /* initialize ADC paths */
4501352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
4502352f7f91STakashi Iwai {
4503352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4504352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
4505352f7f91STakashi Iwai 	struct nid_path *path;
4506352f7f91STakashi Iwai 	int i, c, nums;
4507352f7f91STakashi Iwai 
4508352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4509352f7f91STakashi Iwai 		nums = 1;
4510352f7f91STakashi Iwai 	else
4511352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
4512352f7f91STakashi Iwai 
4513352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
4514352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
4515c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
4516352f7f91STakashi Iwai 			if (path) {
4517352f7f91STakashi Iwai 				bool active = path->active;
4518352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
4519352f7f91STakashi Iwai 					active = true;
4520352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
4521352f7f91STakashi Iwai 			}
4522352f7f91STakashi Iwai 		}
4523352f7f91STakashi Iwai 	}
4524352f7f91STakashi Iwai 
4525352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
4526352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
4527352f7f91STakashi Iwai 
4528352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
4529352f7f91STakashi Iwai 		spec->cap_sync_hook(codec);
4530352f7f91STakashi Iwai }
4531352f7f91STakashi Iwai 
4532352f7f91STakashi Iwai /* set right pin controls for digital I/O */
4533352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
4534352f7f91STakashi Iwai {
4535352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4536352f7f91STakashi Iwai 	int i;
4537352f7f91STakashi Iwai 	hda_nid_t pin;
4538352f7f91STakashi Iwai 
4539d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
45402c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
4541352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
45422430d7b7STakashi Iwai 	if (pin) {
45432430d7b7STakashi Iwai 		struct nid_path *path;
45442c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
45452430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
45462430d7b7STakashi Iwai 		if (path)
45472430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
45482430d7b7STakashi Iwai 	}
4549352f7f91STakashi Iwai }
4550352f7f91STakashi Iwai 
4551973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
4552973e4972STakashi Iwai  * invalid unsol tags by some reason
4553973e4972STakashi Iwai  */
4554973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
4555973e4972STakashi Iwai {
4556973e4972STakashi Iwai 	int i;
4557973e4972STakashi Iwai 
4558973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
4559973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
4560973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
4561973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
4562973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
4563973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
4564973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
4565973e4972STakashi Iwai 	}
4566973e4972STakashi Iwai }
4567973e4972STakashi Iwai 
45685187ac16STakashi Iwai /*
45695187ac16STakashi Iwai  * initialize the generic spec;
45705187ac16STakashi Iwai  * this can be put as patch_ops.init function
45715187ac16STakashi Iwai  */
4572352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
4573352f7f91STakashi Iwai {
4574352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4575352f7f91STakashi Iwai 
4576352f7f91STakashi Iwai 	if (spec->init_hook)
4577352f7f91STakashi Iwai 		spec->init_hook(codec);
4578352f7f91STakashi Iwai 
4579352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
4580352f7f91STakashi Iwai 
45813bbcd274STakashi Iwai 	codec->cached_write = 1;
45823bbcd274STakashi Iwai 
4583352f7f91STakashi Iwai 	init_multi_out(codec);
4584352f7f91STakashi Iwai 	init_extra_out(codec);
4585352f7f91STakashi Iwai 	init_multi_io(codec);
4586352f7f91STakashi Iwai 	init_analog_input(codec);
4587352f7f91STakashi Iwai 	init_input_src(codec);
4588352f7f91STakashi Iwai 	init_digital(codec);
4589352f7f91STakashi Iwai 
4590973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
4591973e4972STakashi Iwai 
4592352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
4593a5cc2509STakashi Iwai 	update_automute_all(codec);
4594352f7f91STakashi Iwai 
45953bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
45963bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
45973bbcd274STakashi Iwai 
4598352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
4599352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4600352f7f91STakashi Iwai 
4601352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
4602352f7f91STakashi Iwai 	return 0;
4603352f7f91STakashi Iwai }
4604fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
4605fce52a3bSTakashi Iwai 
46065187ac16STakashi Iwai /*
46075187ac16STakashi Iwai  * free the generic spec;
46085187ac16STakashi Iwai  * this can be put as patch_ops.free function
46095187ac16STakashi Iwai  */
4610fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
4611fce52a3bSTakashi Iwai {
4612fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
4613fce52a3bSTakashi Iwai 	kfree(codec->spec);
4614fce52a3bSTakashi Iwai 	codec->spec = NULL;
4615fce52a3bSTakashi Iwai }
4616fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
4617fce52a3bSTakashi Iwai 
4618fce52a3bSTakashi Iwai #ifdef CONFIG_PM
46195187ac16STakashi Iwai /*
46205187ac16STakashi Iwai  * check the loopback power save state;
46215187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
46225187ac16STakashi Iwai  */
4623fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4624fce52a3bSTakashi Iwai {
4625fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4626fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4627fce52a3bSTakashi Iwai }
4628fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
4629fce52a3bSTakashi Iwai #endif
4630352f7f91STakashi Iwai 
4631352f7f91STakashi Iwai 
4632352f7f91STakashi Iwai /*
4633352f7f91STakashi Iwai  * the generic codec support
4634352f7f91STakashi Iwai  */
46351da177e4SLinus Torvalds 
4636352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
4637352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
4638352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
4639352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
4640fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
4641352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
464283012a7cSTakashi Iwai #ifdef CONFIG_PM
4643fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
4644cb53c626STakashi Iwai #endif
46451da177e4SLinus Torvalds };
46461da177e4SLinus Torvalds 
46471da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
46481da177e4SLinus Torvalds {
4649352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
46501da177e4SLinus Torvalds 	int err;
46511da177e4SLinus Torvalds 
4652e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4653352f7f91STakashi Iwai 	if (!spec)
46541da177e4SLinus Torvalds 		return -ENOMEM;
4655352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
46561da177e4SLinus Torvalds 	codec->spec = spec;
46571da177e4SLinus Torvalds 
46589eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
46599eb413e5STakashi Iwai 	if (err < 0)
46609eb413e5STakashi Iwai 		return err;
46619eb413e5STakashi Iwai 
46629eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
4663352f7f91STakashi Iwai 	if (err < 0)
46641da177e4SLinus Torvalds 		goto error;
46651da177e4SLinus Torvalds 
46661da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
46671da177e4SLinus Torvalds 	return 0;
46681da177e4SLinus Torvalds 
46691da177e4SLinus Torvalds error:
4670fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
46711da177e4SLinus Torvalds 	return err;
46721da177e4SLinus Torvalds }
4673fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
4674