xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 8e8db7f1)
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 */
753a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
754a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
755352f7f91STakashi Iwai 		       int cidx, unsigned long val)
756352f7f91STakashi Iwai {
757352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
758352f7f91STakashi Iwai 
75912c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
760352f7f91STakashi Iwai 	if (!knew)
761a35bd1e3STakashi Iwai 		return NULL;
762352f7f91STakashi Iwai 	knew->index = cidx;
763352f7f91STakashi Iwai 	if (get_amp_nid_(val))
764352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
765352f7f91STakashi Iwai 	knew->private_value = val;
766a35bd1e3STakashi Iwai 	return knew;
767352f7f91STakashi Iwai }
768352f7f91STakashi Iwai 
769352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
770352f7f91STakashi Iwai 				const char *pfx, const char *dir,
771352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
772352f7f91STakashi Iwai {
773352f7f91STakashi Iwai 	char name[32];
774352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
775a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
776a35bd1e3STakashi Iwai 		return -ENOMEM;
777a35bd1e3STakashi Iwai 	return 0;
778352f7f91STakashi Iwai }
779352f7f91STakashi Iwai 
780352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
781352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
782352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
783352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
784352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
785352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
786352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
787352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
788352f7f91STakashi Iwai 
789352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
790352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
791352f7f91STakashi Iwai {
792352f7f91STakashi Iwai 	unsigned int val;
793352f7f91STakashi Iwai 	if (!path)
794352f7f91STakashi Iwai 		return 0;
795352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
796352f7f91STakashi Iwai 	if (!val)
797352f7f91STakashi Iwai 		return 0;
798352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
799352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
800352f7f91STakashi Iwai }
801352f7f91STakashi Iwai 
802352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
803352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
804352f7f91STakashi Iwai 			       int type)
805352f7f91STakashi Iwai {
806352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
807352f7f91STakashi Iwai 	if (path) {
808352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
809352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
810352f7f91STakashi Iwai 			chs = 3; /* stereo */
811352f7f91STakashi Iwai 	}
812352f7f91STakashi Iwai 	return chs;
813352f7f91STakashi Iwai }
814352f7f91STakashi Iwai 
815352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
816352f7f91STakashi Iwai 			  struct nid_path *path)
817352f7f91STakashi Iwai {
818352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
819352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
820352f7f91STakashi Iwai }
821352f7f91STakashi Iwai 
822352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
823352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
824352f7f91STakashi Iwai  */
825352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
826352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
827352f7f91STakashi Iwai {
828352f7f91STakashi Iwai 	unsigned int val;
829352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
830352f7f91STakashi Iwai 
831352f7f91STakashi Iwai 	if (!path)
832352f7f91STakashi Iwai 		return 0;
833352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
834352f7f91STakashi Iwai 	if (!val)
835352f7f91STakashi Iwai 		return 0;
836352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
837352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
838352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
839352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
840352f7f91STakashi Iwai 		if (nums > 1) {
841352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
842352f7f91STakashi Iwai 			val |= nums << 19;
843352f7f91STakashi Iwai 		}
844352f7f91STakashi Iwai 	}
845352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
846352f7f91STakashi Iwai }
847352f7f91STakashi Iwai 
848352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
849352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
850352f7f91STakashi Iwai {
851352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
852352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
853352f7f91STakashi Iwai }
854352f7f91STakashi Iwai 
855247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
856247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
857247d85eeSTakashi Iwai {
858247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
859247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
860247d85eeSTakashi Iwai }
861247d85eeSTakashi Iwai 
862352f7f91STakashi Iwai static const char * const channel_name[4] = {
863352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
864352f7f91STakashi Iwai };
865352f7f91STakashi Iwai 
866352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
867247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
868247d85eeSTakashi Iwai 				    int *index, int ctl_type)
869352f7f91STakashi Iwai {
870247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
871352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
872352f7f91STakashi Iwai 
873352f7f91STakashi Iwai 	*index = 0;
874352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
875247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
876352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
877352f7f91STakashi Iwai 
878352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
879352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
880352f7f91STakashi Iwai 	 */
881352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
882352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
883352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
884352f7f91STakashi Iwai 
885247d85eeSTakashi Iwai 	/* multi-io channels */
886247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
887247d85eeSTakashi Iwai 		return channel_name[ch];
888247d85eeSTakashi Iwai 
889352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
890352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
891247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
892247d85eeSTakashi Iwai 		 * don't name it as Speaker
893247d85eeSTakashi Iwai 		 */
894247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
895247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
896247d85eeSTakashi Iwai 			break;
897352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
898352f7f91STakashi Iwai 			return "Speaker";
899352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
900352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
901352f7f91STakashi Iwai 		break;
902352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
903247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
904247d85eeSTakashi Iwai 		 * don't name it as Headphone
905247d85eeSTakashi Iwai 		 */
906247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
907247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
908247d85eeSTakashi Iwai 			break;
909352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
910352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
911352f7f91STakashi Iwai 			break;
912352f7f91STakashi Iwai 		*index = ch;
913352f7f91STakashi Iwai 		return "Headphone";
914247d85eeSTakashi Iwai 	}
915247d85eeSTakashi Iwai 
916247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
917352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
918352f7f91STakashi Iwai 		return "PCM";
919247d85eeSTakashi Iwai 
920352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
921352f7f91STakashi Iwai 		snd_BUG();
922352f7f91STakashi Iwai 		return "PCM";
923352f7f91STakashi Iwai 	}
924352f7f91STakashi Iwai 
925352f7f91STakashi Iwai 	return channel_name[ch];
926352f7f91STakashi Iwai }
927352f7f91STakashi Iwai 
928352f7f91STakashi Iwai /*
929352f7f91STakashi Iwai  * Parse output paths
930352f7f91STakashi Iwai  */
931352f7f91STakashi Iwai 
932352f7f91STakashi Iwai /* badness definition */
933352f7f91STakashi Iwai enum {
934352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
935352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
936352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
937352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
938352f7f91STakashi Iwai 	/* No possible multi-ios */
939352f7f91STakashi Iwai 	BAD_MULTI_IO = 0x103,
940352f7f91STakashi Iwai 	/* No individual DAC for extra output */
941352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
942352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
943352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
944352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
945352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
946352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
947352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
948352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
949352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
950352f7f91STakashi Iwai 	/* Volume widget is shared */
951352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
952352f7f91STakashi Iwai };
953352f7f91STakashi Iwai 
9540e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
955352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
956352f7f91STakashi Iwai  *
957352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
958352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
959352f7f91STakashi Iwai  * total badness for both volume and mute controls.
960352f7f91STakashi Iwai  */
9610e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
962352f7f91STakashi Iwai {
963352f7f91STakashi Iwai 	hda_nid_t nid;
964352f7f91STakashi Iwai 	unsigned int val;
965352f7f91STakashi Iwai 	int badness = 0;
966352f7f91STakashi Iwai 
967352f7f91STakashi Iwai 	if (!path)
968352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
9690e614dd0STakashi Iwai 
9700e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
9710e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
9720e614dd0STakashi Iwai 		return 0; /* already evaluated */
9730e614dd0STakashi Iwai 
974352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
975352f7f91STakashi Iwai 	if (nid) {
976352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
977352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
978352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
979352f7f91STakashi Iwai 		else
980352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
981352f7f91STakashi Iwai 	} else
982352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
983352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
984352f7f91STakashi Iwai 	if (nid) {
985352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
986352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
987352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
988352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
989352f7f91STakashi Iwai 		else
990352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
991352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
992352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
993352f7f91STakashi Iwai 		else
994352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
995352f7f91STakashi Iwai 	} else
996352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
997352f7f91STakashi Iwai 	return badness;
998352f7f91STakashi Iwai }
999352f7f91STakashi Iwai 
1000352f7f91STakashi Iwai struct badness_table {
1001352f7f91STakashi Iwai 	int no_primary_dac;	/* no primary DAC */
1002352f7f91STakashi Iwai 	int no_dac;		/* no secondary DACs */
1003352f7f91STakashi Iwai 	int shared_primary;	/* primary DAC is shared with main output */
1004352f7f91STakashi Iwai 	int shared_surr;	/* secondary DAC shared with main or primary */
1005352f7f91STakashi Iwai 	int shared_clfe;	/* third DAC shared with main or primary */
1006352f7f91STakashi Iwai 	int shared_surr_main;	/* secondary DAC sahred with main/DAC0 */
1007352f7f91STakashi Iwai };
1008352f7f91STakashi Iwai 
1009352f7f91STakashi Iwai static struct badness_table main_out_badness = {
1010352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1011352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1012352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1013352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1014352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1015352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1016352f7f91STakashi Iwai };
1017352f7f91STakashi Iwai 
1018352f7f91STakashi Iwai static struct badness_table extra_out_badness = {
1019352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1020352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1021352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1022352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1023352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1024352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1025352f7f91STakashi Iwai };
1026352f7f91STakashi Iwai 
10277385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
10287385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
10297385df61STakashi Iwai {
10307385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10317385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
10327385df61STakashi Iwai 
10337385df61STakashi Iwai 	if (cfg->line_outs > idx)
10347385df61STakashi Iwai 		return spec->private_dac_nids[idx];
10357385df61STakashi Iwai 	idx -= cfg->line_outs;
10367385df61STakashi Iwai 	if (spec->multi_ios > idx)
10377385df61STakashi Iwai 		return spec->multi_io[idx].dac;
10387385df61STakashi Iwai 	return 0;
10397385df61STakashi Iwai }
10407385df61STakashi Iwai 
10417385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
10427385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
10437385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
10447385df61STakashi Iwai {
10457385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
10467385df61STakashi Iwai }
10477385df61STakashi Iwai 
1048352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1049352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1050352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1051196c1766STakashi Iwai 			   int *path_idx,
1052352f7f91STakashi Iwai 			   const struct badness_table *bad)
1053352f7f91STakashi Iwai {
1054352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1055352f7f91STakashi Iwai 	int i, j;
1056352f7f91STakashi Iwai 	int badness = 0;
1057352f7f91STakashi Iwai 	hda_nid_t dac;
1058352f7f91STakashi Iwai 
1059352f7f91STakashi Iwai 	if (!num_outs)
1060352f7f91STakashi Iwai 		return 0;
1061352f7f91STakashi Iwai 
1062352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
10630c8c0f56STakashi Iwai 		struct nid_path *path;
1064352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
10651e0b5286STakashi Iwai 
10660e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
10670e614dd0STakashi Iwai 		if (path) {
10680e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
10691e0b5286STakashi Iwai 			continue;
10701e0b5286STakashi Iwai 		}
10711e0b5286STakashi Iwai 
1072352f7f91STakashi Iwai 		dacs[i] = look_for_dac(codec, pin, false);
1073352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1074980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1075352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1076352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1077352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1078352f7f91STakashi Iwai 					dacs[j] = 0;
1079980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1080196c1766STakashi Iwai 					path_idx[j] = 0;
1081352f7f91STakashi Iwai 					break;
1082352f7f91STakashi Iwai 				}
1083352f7f91STakashi Iwai 			}
1084352f7f91STakashi Iwai 		}
1085352f7f91STakashi Iwai 		dac = dacs[i];
1086352f7f91STakashi Iwai 		if (!dac) {
10877385df61STakashi Iwai 			if (num_outs > 2)
10887385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
10897385df61STakashi Iwai 			if (!dac)
10907385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
10917385df61STakashi Iwai 			if (!dac)
10927385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1093352f7f91STakashi Iwai 			if (dac) {
1094352f7f91STakashi Iwai 				if (!i)
1095352f7f91STakashi Iwai 					badness += bad->shared_primary;
1096352f7f91STakashi Iwai 				else if (i == 1)
1097352f7f91STakashi Iwai 					badness += bad->shared_surr;
1098352f7f91STakashi Iwai 				else
1099352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1100352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1101352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1102352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1103352f7f91STakashi Iwai 			} else if (!i)
1104352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1105352f7f91STakashi Iwai 			else
1106352f7f91STakashi Iwai 				badness += bad->no_dac;
1107352f7f91STakashi Iwai 		}
11083ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1109117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1110b3a8c745STakashi Iwai 			/* try with aamix */
11113ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1112b3a8c745STakashi Iwai 		}
11130c8c0f56STakashi Iwai 		if (!path)
1114352f7f91STakashi Iwai 			dac = dacs[i] = 0;
1115e1284af7STakashi Iwai 		else {
11160c8c0f56STakashi Iwai 			print_nid_path("output", path);
1117e1284af7STakashi Iwai 			path->active = true;
1118196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
11190e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1120e1284af7STakashi Iwai 		}
1121352f7f91STakashi Iwai 	}
1122352f7f91STakashi Iwai 
1123352f7f91STakashi Iwai 	return badness;
1124352f7f91STakashi Iwai }
1125352f7f91STakashi Iwai 
1126352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1127352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1128352f7f91STakashi Iwai {
1129352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1130352f7f91STakashi Iwai 	int i;
1131352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1132352f7f91STakashi Iwai 
1133352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1134352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1135352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1136352f7f91STakashi Iwai 			continue;
1137352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1138352f7f91STakashi Iwai 			if (nid_found)
1139352f7f91STakashi Iwai 				return 0;
1140352f7f91STakashi Iwai 			nid_found = nid;
1141352f7f91STakashi Iwai 		}
1142352f7f91STakashi Iwai 	}
1143352f7f91STakashi Iwai 	return nid_found;
1144352f7f91STakashi Iwai }
1145352f7f91STakashi Iwai 
1146352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1147352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1148352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1149352f7f91STakashi Iwai {
1150352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1151352f7f91STakashi Iwai 
1152352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1153352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1154352f7f91STakashi Iwai 		return false;
1155352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1156352f7f91STakashi Iwai 		return false;
1157352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1158352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1159352f7f91STakashi Iwai 		return false;
1160352f7f91STakashi Iwai 	return true;
1161352f7f91STakashi Iwai }
1162352f7f91STakashi Iwai 
1163e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1164e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1165e22aab7dSTakashi Iwai {
1166e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1167e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1168e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1169e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1170e22aab7dSTakashi Iwai 	int type, i;
1171e22aab7dSTakashi Iwai 	int num_pins = 0;
1172e22aab7dSTakashi Iwai 
1173e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1174e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1175e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1176e22aab7dSTakashi Iwai 				continue;
1177e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1178e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1179e22aab7dSTakashi Iwai 				num_pins++;
1180e22aab7dSTakashi Iwai 		}
1181e22aab7dSTakashi Iwai 	}
1182e22aab7dSTakashi Iwai 	return num_pins;
1183e22aab7dSTakashi Iwai }
1184e22aab7dSTakashi Iwai 
1185352f7f91STakashi Iwai /*
1186352f7f91STakashi Iwai  * multi-io helper
1187352f7f91STakashi Iwai  *
1188352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1189352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1190352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1191352f7f91STakashi Iwai  * the badness value.
1192352f7f91STakashi Iwai  */
1193352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1194352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1195e22aab7dSTakashi Iwai 			  bool hardwired)
1196352f7f91STakashi Iwai {
1197352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1198352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1199e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1200352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1201352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1202352f7f91STakashi Iwai 	int badness = 0;
12030e614dd0STakashi Iwai 	struct nid_path *path;
1204352f7f91STakashi Iwai 
1205352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1206352f7f91STakashi Iwai 	if (old_pins >= 2)
1207352f7f91STakashi Iwai 		goto end_fill;
1208352f7f91STakashi Iwai 
1209e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1210352f7f91STakashi Iwai 	if (num_pins < 2)
1211352f7f91STakashi Iwai 		goto end_fill;
1212352f7f91STakashi Iwai 
1213352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1214352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1215352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1216352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1217352f7f91STakashi Iwai 
1218352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1219352f7f91STakashi Iwai 				continue;
1220352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1221352f7f91STakashi Iwai 				continue;
1222352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1223352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1224352f7f91STakashi Iwai 					break;
1225352f7f91STakashi Iwai 			}
1226352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1227352f7f91STakashi Iwai 				continue;
1228352f7f91STakashi Iwai 
1229352f7f91STakashi Iwai 			if (hardwired)
1230352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1231352f7f91STakashi Iwai 			else if (!dac)
1232352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1233352f7f91STakashi Iwai 			if (!dac) {
1234352f7f91STakashi Iwai 				badness++;
1235352f7f91STakashi Iwai 				continue;
1236352f7f91STakashi Iwai 			}
12373ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
12383ca529d3STakashi Iwai 						    -spec->mixer_nid);
12390c8c0f56STakashi Iwai 			if (!path) {
1240352f7f91STakashi Iwai 				badness++;
1241352f7f91STakashi Iwai 				continue;
1242352f7f91STakashi Iwai 			}
12430c8c0f56STakashi Iwai 			print_nid_path("multiio", path);
1244352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1245352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1246196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1247196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1248352f7f91STakashi Iwai 			spec->multi_ios++;
1249352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1250352f7f91STakashi Iwai 				break;
1251352f7f91STakashi Iwai 		}
1252352f7f91STakashi Iwai 	}
1253352f7f91STakashi Iwai  end_fill:
1254352f7f91STakashi Iwai 	if (badness)
1255352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1256352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1257352f7f91STakashi Iwai 		if (hardwired)
1258352f7f91STakashi Iwai 			return 1; /* nothing found */
1259352f7f91STakashi Iwai 		else
1260352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1261352f7f91STakashi Iwai 	}
1262352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1263352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1264352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1265352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1266352f7f91STakashi Iwai 		return badness;
1267352f7f91STakashi Iwai 	}
1268352f7f91STakashi Iwai 
1269352f7f91STakashi Iwai 	/* assign volume and mute controls */
12700e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
12710e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
12720e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
12730e614dd0STakashi Iwai 	}
1274352f7f91STakashi Iwai 
1275352f7f91STakashi Iwai 	return badness;
1276352f7f91STakashi Iwai }
1277352f7f91STakashi Iwai 
1278352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1279352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1280196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1281352f7f91STakashi Iwai {
1282b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1283352f7f91STakashi Iwai 	int i;
1284352f7f91STakashi Iwai 	bool found = false;
1285352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
12860c8c0f56STakashi Iwai 		struct nid_path *path;
1287352f7f91STakashi Iwai 		hda_nid_t dac;
1288352f7f91STakashi Iwai 		if (dacs[i])
1289352f7f91STakashi Iwai 			continue;
1290352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1291352f7f91STakashi Iwai 		if (!dac)
1292352f7f91STakashi Iwai 			continue;
12933ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
12943ca529d3STakashi Iwai 					    -spec->mixer_nid);
1295117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
12963ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
12970c8c0f56STakashi Iwai 		if (path) {
1298352f7f91STakashi Iwai 			dacs[i] = dac;
1299352f7f91STakashi Iwai 			found = true;
13000c8c0f56STakashi Iwai 			print_nid_path("output", path);
1301e1284af7STakashi Iwai 			path->active = true;
1302196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1303352f7f91STakashi Iwai 		}
1304352f7f91STakashi Iwai 	}
1305352f7f91STakashi Iwai 	return found;
1306352f7f91STakashi Iwai }
1307352f7f91STakashi Iwai 
1308c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1309c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1310c30aa7b2STakashi Iwai {
13113ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1312c30aa7b2STakashi Iwai 	struct nid_path *path;
1313c30aa7b2STakashi Iwai 
1314c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
13153ca529d3STakashi Iwai 	if (!path || !path->depth ||
13163ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1317c30aa7b2STakashi Iwai 		return 0;
1318c30aa7b2STakashi Iwai 	path = snd_hda_add_new_path(codec, path->path[0],
1319c30aa7b2STakashi Iwai 				    path->path[path->depth - 1],
13203ca529d3STakashi Iwai 				    spec->mixer_nid);
1321c30aa7b2STakashi Iwai 	if (!path)
1322c30aa7b2STakashi Iwai 		return 0;
1323c30aa7b2STakashi Iwai 	print_nid_path("output-aamix", path);
1324c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
1325c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1326c30aa7b2STakashi Iwai }
1327c30aa7b2STakashi Iwai 
1328a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1329a07a949bSTakashi Iwai  * shared dac pointed by the paths
1330a07a949bSTakashi Iwai  */
1331a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1332a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1333a07a949bSTakashi Iwai {
1334a07a949bSTakashi Iwai 	struct nid_path *path;
1335a07a949bSTakashi Iwai 	int i;
1336a07a949bSTakashi Iwai 
1337a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1338a07a949bSTakashi Iwai 		if (dacs[i])
1339a07a949bSTakashi Iwai 			continue;
1340a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1341a07a949bSTakashi Iwai 		if (!path)
1342a07a949bSTakashi Iwai 			continue;
1343a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1344a07a949bSTakashi Iwai 	}
1345a07a949bSTakashi Iwai }
1346a07a949bSTakashi Iwai 
1347352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1348352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1349352f7f91STakashi Iwai 			      bool fill_hardwired,
1350352f7f91STakashi Iwai 			      bool fill_mio_first)
1351352f7f91STakashi Iwai {
1352352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1353352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1354352f7f91STakashi Iwai 	int i, err, badness;
1355ea46c3c8STakashi Iwai 	unsigned int val;
1356352f7f91STakashi Iwai 
1357352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1358352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1359352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1360352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1361352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1362352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1363352f7f91STakashi Iwai 	spec->multi_ios = 0;
1364352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1365cd5be3f9STakashi Iwai 
1366cd5be3f9STakashi Iwai 	/* clear path indices */
1367cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1368cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1369cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1370cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1371cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1372c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1373cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1374cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1375cd5be3f9STakashi Iwai 
1376352f7f91STakashi Iwai 	badness = 0;
1377352f7f91STakashi Iwai 
1378352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1379352f7f91STakashi Iwai 	if (fill_hardwired) {
1380352f7f91STakashi Iwai 		bool mapped;
1381352f7f91STakashi Iwai 		do {
1382352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1383352f7f91STakashi Iwai 					     cfg->line_out_pins,
1384196c1766STakashi Iwai 					     spec->private_dac_nids,
1385196c1766STakashi Iwai 					     spec->out_paths);
1386352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1387352f7f91STakashi Iwai 					      cfg->hp_pins,
1388196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1389196c1766STakashi Iwai 					      spec->hp_paths);
1390352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1391352f7f91STakashi Iwai 					      cfg->speaker_pins,
1392196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1393196c1766STakashi Iwai 					      spec->speaker_paths);
1394352f7f91STakashi Iwai 			if (fill_mio_first && cfg->line_outs == 1 &&
1395352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1396e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1397352f7f91STakashi Iwai 				if (!err)
1398352f7f91STakashi Iwai 					mapped = true;
1399352f7f91STakashi Iwai 			}
1400352f7f91STakashi Iwai 		} while (mapped);
1401352f7f91STakashi Iwai 	}
1402352f7f91STakashi Iwai 
1403352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1404196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
1405352f7f91STakashi Iwai 				   &main_out_badness);
1406352f7f91STakashi Iwai 
1407352f7f91STakashi Iwai 	if (fill_mio_first &&
1408352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1409352f7f91STakashi Iwai 		/* try to fill multi-io first */
1410e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1411352f7f91STakashi Iwai 		if (err < 0)
1412352f7f91STakashi Iwai 			return err;
1413352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1414352f7f91STakashi Iwai 	}
1415352f7f91STakashi Iwai 
1416352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1417352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1418352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1419196c1766STakashi Iwai 				      spec->hp_paths,
1420352f7f91STakashi Iwai 				      &extra_out_badness);
1421352f7f91STakashi Iwai 		if (err < 0)
1422352f7f91STakashi Iwai 			return err;
1423352f7f91STakashi Iwai 		badness += err;
1424352f7f91STakashi Iwai 	}
1425352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1426352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1427352f7f91STakashi Iwai 				      cfg->speaker_pins,
1428352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1429196c1766STakashi Iwai 				      spec->speaker_paths,
1430352f7f91STakashi Iwai 				      &extra_out_badness);
1431352f7f91STakashi Iwai 		if (err < 0)
1432352f7f91STakashi Iwai 			return err;
1433352f7f91STakashi Iwai 		badness += err;
1434352f7f91STakashi Iwai 	}
1435352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1436e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1437352f7f91STakashi Iwai 		if (err < 0)
1438352f7f91STakashi Iwai 			return err;
1439352f7f91STakashi Iwai 		badness += err;
1440352f7f91STakashi Iwai 	}
1441e22aab7dSTakashi Iwai 
1442c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1443c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1444c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1445c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1446c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1447c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1448c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1449c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1450c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1451c30aa7b2STakashi Iwai 	}
1452c30aa7b2STakashi Iwai 
1453e22aab7dSTakashi Iwai 	if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1454e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1455e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1456352f7f91STakashi Iwai 
1457a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1458a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1459a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1460a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1461a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1462a07a949bSTakashi Iwai 		else {
1463a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1464a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1465a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1466a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1467a07a949bSTakashi Iwai 		}
1468a07a949bSTakashi Iwai 	}
1469a07a949bSTakashi Iwai 
1470a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1471c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1472a07a949bSTakashi Iwai 
1473352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1474352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1475352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1476352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1477352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1478352f7f91STakashi Iwai 		spec->multi_ios = 0;
1479352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1480352f7f91STakashi Iwai 	}
1481352f7f91STakashi Iwai 
1482a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1483a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1484a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1485a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1486a07a949bSTakashi Iwai 				   spec->hp_paths);
1487a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1488a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1489a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1490a07a949bSTakashi Iwai 				   spec->speaker_paths);
1491a07a949bSTakashi Iwai 
14922c12c30dSTakashi Iwai 	/* set initial pinctl targets */
1493ea46c3c8STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
1494ea46c3c8STakashi Iwai 		val = PIN_HP;
1495ea46c3c8STakashi Iwai 	else
1496ea46c3c8STakashi Iwai 		val = PIN_OUT;
1497ea46c3c8STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
14982c12c30dSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
14992c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
1500ea46c3c8STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1501ea46c3c8STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
15022c12c30dSTakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
1503ea46c3c8STakashi Iwai 				cfg->speaker_pins, val);
1504ea46c3c8STakashi Iwai 	}
15052c12c30dSTakashi Iwai 
1506352f7f91STakashi Iwai 	return badness;
1507352f7f91STakashi Iwai }
1508352f7f91STakashi Iwai 
1509352f7f91STakashi Iwai #define DEBUG_BADNESS
1510352f7f91STakashi Iwai 
1511352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1512352f7f91STakashi Iwai #define debug_badness	snd_printdd
1513352f7f91STakashi Iwai #else
1514352f7f91STakashi Iwai #define debug_badness(...)
1515352f7f91STakashi Iwai #endif
1516352f7f91STakashi Iwai 
1517352f7f91STakashi Iwai static void debug_show_configs(struct hda_gen_spec *spec, struct auto_pin_cfg *cfg)
1518352f7f91STakashi Iwai {
1519352f7f91STakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1520352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1521708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1522352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1523352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1524352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1525352f7f91STakashi Iwai 		      spec->multiout.dac_nids[3]);
1526352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1527352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1528352f7f91STakashi Iwai 			      spec->multi_ios,
1529352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1530352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1531352f7f91STakashi Iwai 	debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1532352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1533708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1534352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1535352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1536352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1537352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1538352f7f91STakashi Iwai 	debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1539352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1540352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1541352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1542352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1543352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1544352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1545352f7f91STakashi Iwai }
1546352f7f91STakashi Iwai 
1547352f7f91STakashi Iwai /* find all available DACs of the codec */
1548352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1549352f7f91STakashi Iwai {
1550352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1551352f7f91STakashi Iwai 	int i;
1552352f7f91STakashi Iwai 	hda_nid_t nid = codec->start_nid;
1553352f7f91STakashi Iwai 
1554352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1555352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1556352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
1557352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1558352f7f91STakashi Iwai 			continue;
1559352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1560352f7f91STakashi Iwai 			snd_printk(KERN_ERR "hda: Too many DACs!\n");
1561352f7f91STakashi Iwai 			break;
1562352f7f91STakashi Iwai 		}
1563352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1564352f7f91STakashi Iwai 	}
1565352f7f91STakashi Iwai }
1566352f7f91STakashi Iwai 
1567352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1568352f7f91STakashi Iwai {
1569352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1570352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1571352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
1572352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1573352f7f91STakashi Iwai 	int badness;
1574352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1575352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1576352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1577352f7f91STakashi Iwai 
1578352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1579352f7f91STakashi Iwai 	if (!best_cfg)
1580352f7f91STakashi Iwai 		return -ENOMEM;
1581352f7f91STakashi Iwai 	*best_cfg = *cfg;
1582352f7f91STakashi Iwai 
1583352f7f91STakashi Iwai 	for (;;) {
1584352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1585352f7f91STakashi Iwai 					     fill_mio_first);
1586352f7f91STakashi Iwai 		if (badness < 0) {
1587352f7f91STakashi Iwai 			kfree(best_cfg);
1588352f7f91STakashi Iwai 			return badness;
1589352f7f91STakashi Iwai 		}
1590352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1591352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1592352f7f91STakashi Iwai 			      badness);
1593352f7f91STakashi Iwai 		debug_show_configs(spec, cfg);
1594352f7f91STakashi Iwai 		if (badness < best_badness) {
1595352f7f91STakashi Iwai 			best_badness = badness;
1596352f7f91STakashi Iwai 			*best_cfg = *cfg;
1597352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1598352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1599352f7f91STakashi Iwai 		}
1600352f7f91STakashi Iwai 		if (!badness)
1601352f7f91STakashi Iwai 			break;
1602352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
1603352f7f91STakashi Iwai 		if (!fill_mio_first)
1604352f7f91STakashi Iwai 			continue;
1605352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
1606352f7f91STakashi Iwai 		if (!fill_hardwired)
1607352f7f91STakashi Iwai 			continue;
1608352f7f91STakashi Iwai 		if (hp_spk_swapped)
1609352f7f91STakashi Iwai 			break;
1610352f7f91STakashi Iwai 		hp_spk_swapped = true;
1611352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
1612352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
1613352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
1614352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
1615352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1616352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
1617352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
1618352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1619352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
1620352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
1621352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
1622352f7f91STakashi Iwai 			fill_hardwired = true;
1623352f7f91STakashi Iwai 			continue;
1624352f7f91STakashi Iwai 		}
1625352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
1626352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
1627352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
1628352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
1629352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
1630352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
1631352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
1632352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
1633352f7f91STakashi Iwai 			cfg->hp_outs = 0;
1634352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
1635352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
1636352f7f91STakashi Iwai 			fill_hardwired = true;
1637352f7f91STakashi Iwai 			continue;
1638352f7f91STakashi Iwai 		}
1639352f7f91STakashi Iwai 		break;
1640352f7f91STakashi Iwai 	}
1641352f7f91STakashi Iwai 
1642352f7f91STakashi Iwai 	if (badness) {
16430c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
1644352f7f91STakashi Iwai 		*cfg = *best_cfg;
1645352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
1646352f7f91STakashi Iwai 	}
1647352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
1648352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
1649352f7f91STakashi Iwai 	debug_show_configs(spec, cfg);
1650352f7f91STakashi Iwai 
1651352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
1652352f7f91STakashi Iwai 		struct nid_path *path;
1653196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
1654352f7f91STakashi Iwai 		if (path)
1655352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
16567a71bbf3STakashi Iwai 		if (spec->vmaster_nid)
16577a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
16587a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
1659352f7f91STakashi Iwai 	}
1660352f7f91STakashi Iwai 
1661352f7f91STakashi Iwai 	kfree(best_cfg);
1662352f7f91STakashi Iwai 	return 0;
1663352f7f91STakashi Iwai }
1664352f7f91STakashi Iwai 
1665352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
1666352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
1667352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
1668352f7f91STakashi Iwai {
1669352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1670352f7f91STakashi Iwai 	int i, err, noutputs;
1671352f7f91STakashi Iwai 
1672352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
1673352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
1674352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
1675352f7f91STakashi Iwai 
1676352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
1677352f7f91STakashi Iwai 		const char *name;
1678352f7f91STakashi Iwai 		int index;
1679352f7f91STakashi Iwai 		struct nid_path *path;
1680352f7f91STakashi Iwai 
1681196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1682352f7f91STakashi Iwai 		if (!path)
1683352f7f91STakashi Iwai 			continue;
1684247d85eeSTakashi Iwai 
1685247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
1686352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1687352f7f91STakashi Iwai 			/* Center/LFE */
1688352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
1689352f7f91STakashi Iwai 			if (err < 0)
1690352f7f91STakashi Iwai 				return err;
1691352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
1692352f7f91STakashi Iwai 			if (err < 0)
1693352f7f91STakashi Iwai 				return err;
1694247d85eeSTakashi Iwai 		} else {
1695247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
1696247d85eeSTakashi Iwai 			if (err < 0)
1697247d85eeSTakashi Iwai 				return err;
1698247d85eeSTakashi Iwai 		}
1699247d85eeSTakashi Iwai 
1700247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
1701247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
1702352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
1703352f7f91STakashi Iwai 			if (err < 0)
1704352f7f91STakashi Iwai 				return err;
1705352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
1706352f7f91STakashi Iwai 			if (err < 0)
1707352f7f91STakashi Iwai 				return err;
1708352f7f91STakashi Iwai 		} else {
1709352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
1710352f7f91STakashi Iwai 			if (err < 0)
1711352f7f91STakashi Iwai 				return err;
1712352f7f91STakashi Iwai 		}
1713352f7f91STakashi Iwai 	}
1714352f7f91STakashi Iwai 	return 0;
1715352f7f91STakashi Iwai }
1716352f7f91STakashi Iwai 
1717c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
1718196c1766STakashi Iwai 			    const char *pfx, int cidx)
1719352f7f91STakashi Iwai {
1720352f7f91STakashi Iwai 	struct nid_path *path;
1721352f7f91STakashi Iwai 	int err;
1722352f7f91STakashi Iwai 
1723196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
1724352f7f91STakashi Iwai 	if (!path)
1725352f7f91STakashi Iwai 		return 0;
1726352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
1727352f7f91STakashi Iwai 	if (err < 0)
1728352f7f91STakashi Iwai 		return err;
1729352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
1730352f7f91STakashi Iwai 	if (err < 0)
1731352f7f91STakashi Iwai 		return err;
1732352f7f91STakashi Iwai 	return 0;
1733352f7f91STakashi Iwai }
1734352f7f91STakashi Iwai 
1735352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
1736352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
1737196c1766STakashi Iwai 			     const int *paths, const char *pfx)
1738352f7f91STakashi Iwai {
1739c2c80383STakashi Iwai 	int i;
1740352f7f91STakashi Iwai 
1741352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
1742c2c80383STakashi Iwai 		const char *name;
1743c2c80383STakashi Iwai 		char tmp[44];
1744c2c80383STakashi Iwai 		int err, idx = 0;
1745c2c80383STakashi Iwai 
1746c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
1747c2c80383STakashi Iwai 			name = "Bass Speaker";
1748c2c80383STakashi Iwai 		else if (num_pins >= 3) {
1749c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
1750352f7f91STakashi Iwai 				 pfx, channel_name[i]);
1751c2c80383STakashi Iwai 			name = tmp;
1752352f7f91STakashi Iwai 		} else {
1753c2c80383STakashi Iwai 			name = pfx;
1754c2c80383STakashi Iwai 			idx = i;
1755352f7f91STakashi Iwai 		}
1756c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
1757352f7f91STakashi Iwai 		if (err < 0)
1758352f7f91STakashi Iwai 			return err;
1759352f7f91STakashi Iwai 	}
1760352f7f91STakashi Iwai 	return 0;
1761352f7f91STakashi Iwai }
1762352f7f91STakashi Iwai 
1763352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
1764352f7f91STakashi Iwai {
1765352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1766352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
1767196c1766STakashi Iwai 				 spec->hp_paths,
1768352f7f91STakashi Iwai 				 "Headphone");
1769352f7f91STakashi Iwai }
1770352f7f91STakashi Iwai 
1771352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
1772352f7f91STakashi Iwai {
1773352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1774352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
1775196c1766STakashi Iwai 				 spec->speaker_paths,
1776352f7f91STakashi Iwai 				 "Speaker");
1777352f7f91STakashi Iwai }
1778352f7f91STakashi Iwai 
1779352f7f91STakashi Iwai /*
178038cf6f1aSTakashi Iwai  * independent HP controls
178138cf6f1aSTakashi Iwai  */
178238cf6f1aSTakashi Iwai 
178338cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
178438cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
178538cf6f1aSTakashi Iwai {
178638cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
178738cf6f1aSTakashi Iwai }
178838cf6f1aSTakashi Iwai 
178938cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
179038cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
179138cf6f1aSTakashi Iwai {
179238cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
179338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
179438cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
179538cf6f1aSTakashi Iwai 	return 0;
179638cf6f1aSTakashi Iwai }
179738cf6f1aSTakashi Iwai 
179838cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
179938cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
180038cf6f1aSTakashi Iwai {
180138cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
180238cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
180338cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
180438cf6f1aSTakashi Iwai 	int ret = 0;
180538cf6f1aSTakashi Iwai 
180638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
180738cf6f1aSTakashi Iwai 	if (spec->active_streams) {
180838cf6f1aSTakashi Iwai 		ret = -EBUSY;
180938cf6f1aSTakashi Iwai 		goto unlock;
181038cf6f1aSTakashi Iwai 	}
181138cf6f1aSTakashi Iwai 
181238cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
181338cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
181438cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
181538cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = 0;
181638cf6f1aSTakashi Iwai 		else
181738cf6f1aSTakashi Iwai 			spec->multiout.hp_out_nid[0] = spec->alt_dac_nid;
181838cf6f1aSTakashi Iwai 		ret = 1;
181938cf6f1aSTakashi Iwai 	}
182038cf6f1aSTakashi Iwai  unlock:
182138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
182238cf6f1aSTakashi Iwai 	return ret;
182338cf6f1aSTakashi Iwai }
182438cf6f1aSTakashi Iwai 
182538cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
182638cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
182738cf6f1aSTakashi Iwai 	.name = "Independent HP",
182838cf6f1aSTakashi Iwai 	.info = indep_hp_info,
182938cf6f1aSTakashi Iwai 	.get = indep_hp_get,
183038cf6f1aSTakashi Iwai 	.put = indep_hp_put,
183138cf6f1aSTakashi Iwai };
183238cf6f1aSTakashi Iwai 
183338cf6f1aSTakashi Iwai 
183438cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
183538cf6f1aSTakashi Iwai {
183638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
183738cf6f1aSTakashi Iwai 
183838cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
183938cf6f1aSTakashi Iwai 		return 0;
184038cf6f1aSTakashi Iwai 	if (!spec->multiout.hp_out_nid[0]) {
184138cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
184238cf6f1aSTakashi Iwai 		return 0;
184338cf6f1aSTakashi Iwai 	}
184438cf6f1aSTakashi Iwai 
184538cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
184638cf6f1aSTakashi Iwai 	spec->alt_dac_nid = spec->multiout.hp_out_nid[0];
184738cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
184838cf6f1aSTakashi Iwai 		return -ENOMEM;
184938cf6f1aSTakashi Iwai 	return 0;
185038cf6f1aSTakashi Iwai }
185138cf6f1aSTakashi Iwai 
185238cf6f1aSTakashi Iwai /*
1853352f7f91STakashi Iwai  * channel mode enum control
1854352f7f91STakashi Iwai  */
1855352f7f91STakashi Iwai 
1856352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
1857352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
1858352f7f91STakashi Iwai {
1859352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1860352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1861a07a949bSTakashi Iwai 	int chs;
1862352f7f91STakashi Iwai 
1863352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1864352f7f91STakashi Iwai 	uinfo->count = 1;
1865352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
1866352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
1867352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
1868a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
1869a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
1870352f7f91STakashi Iwai 	return 0;
1871352f7f91STakashi Iwai }
1872352f7f91STakashi Iwai 
1873352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
1874352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1875352f7f91STakashi Iwai {
1876352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1877352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1878a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
1879a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
1880352f7f91STakashi Iwai 	return 0;
1881352f7f91STakashi Iwai }
1882352f7f91STakashi Iwai 
1883196c1766STakashi Iwai static inline struct nid_path *
1884196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
1885196c1766STakashi Iwai {
1886196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1887196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
1888196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
1889196c1766STakashi Iwai }
1890196c1766STakashi Iwai 
1891a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
1892a5cc2509STakashi Iwai 
1893352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
1894352f7f91STakashi Iwai {
1895352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1896352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
1897352f7f91STakashi Iwai 	struct nid_path *path;
1898352f7f91STakashi Iwai 
1899196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
1900352f7f91STakashi Iwai 	if (!path)
1901352f7f91STakashi Iwai 		return -EINVAL;
1902352f7f91STakashi Iwai 
1903352f7f91STakashi Iwai 	if (path->active == output)
1904352f7f91STakashi Iwai 		return 0;
1905352f7f91STakashi Iwai 
1906352f7f91STakashi Iwai 	if (output) {
19072c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
1908352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, true, true);
1909d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
1910352f7f91STakashi Iwai 	} else {
1911d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
1912352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, true);
19132c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
1914352f7f91STakashi Iwai 	}
1915a365fed9STakashi Iwai 
1916a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
1917a5cc2509STakashi Iwai 	update_automute_all(codec);
1918a365fed9STakashi Iwai 
1919352f7f91STakashi Iwai 	return 0;
1920352f7f91STakashi Iwai }
1921352f7f91STakashi Iwai 
1922352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
1923352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
1924352f7f91STakashi Iwai {
1925352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1926352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1927352f7f91STakashi Iwai 	int i, ch;
1928352f7f91STakashi Iwai 
1929352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
1930352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
1931352f7f91STakashi Iwai 		return -EINVAL;
1932a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
1933352f7f91STakashi Iwai 		return 0;
1934a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
1935352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1936352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
1937352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
1938352f7f91STakashi Iwai 					  spec->const_channel_count);
1939352f7f91STakashi Iwai 	if (spec->need_dac_fix)
1940352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
1941352f7f91STakashi Iwai 	return 1;
1942352f7f91STakashi Iwai }
1943352f7f91STakashi Iwai 
1944352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
1945352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1946352f7f91STakashi Iwai 	.name = "Channel Mode",
1947352f7f91STakashi Iwai 	.info = ch_mode_info,
1948352f7f91STakashi Iwai 	.get = ch_mode_get,
1949352f7f91STakashi Iwai 	.put = ch_mode_put,
1950352f7f91STakashi Iwai };
1951352f7f91STakashi Iwai 
1952352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
1953352f7f91STakashi Iwai {
1954352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1955352f7f91STakashi Iwai 
1956352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
195712c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
1958352f7f91STakashi Iwai 			return -ENOMEM;
1959352f7f91STakashi Iwai 	}
1960352f7f91STakashi Iwai 	return 0;
1961352f7f91STakashi Iwai }
1962352f7f91STakashi Iwai 
1963352f7f91STakashi Iwai /*
1964c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
1965c30aa7b2STakashi Iwai  */
1966c30aa7b2STakashi Iwai 
1967c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
1968c30aa7b2STakashi Iwai 
1969c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
1970c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1971c30aa7b2STakashi Iwai {
1972c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1973c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1974c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
1975c30aa7b2STakashi Iwai 	return 0;
1976c30aa7b2STakashi Iwai }
1977c30aa7b2STakashi Iwai 
1978c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1979c30aa7b2STakashi Iwai 			       int nomix_path_idx, int mix_path_idx)
1980c30aa7b2STakashi Iwai {
1981c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
1982c30aa7b2STakashi Iwai 
1983c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
1984c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
1985c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
1986c30aa7b2STakashi Iwai 		return;
1987c30aa7b2STakashi Iwai 	if (do_mix) {
1988c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
1989c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
1990c30aa7b2STakashi Iwai 	} else {
1991c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, true);
1992c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, true);
1993c30aa7b2STakashi Iwai 	}
1994c30aa7b2STakashi Iwai }
1995c30aa7b2STakashi Iwai 
1996c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
1997c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
1998c30aa7b2STakashi Iwai {
1999c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2000c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2001c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2002c30aa7b2STakashi Iwai 
2003c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2004c30aa7b2STakashi Iwai 		return 0;
2005c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2006c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->out_paths[0],
2007c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[0]);
2008c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->hp_paths[0],
2009c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[1]);
2010c30aa7b2STakashi Iwai 	update_aamix_paths(codec, val, spec->speaker_paths[0],
2011c30aa7b2STakashi Iwai 			   spec->aamix_out_paths[2]);
2012c30aa7b2STakashi Iwai 	return 1;
2013c30aa7b2STakashi Iwai }
2014c30aa7b2STakashi Iwai 
2015c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2016c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2017c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2018c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2019c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2020c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2021c30aa7b2STakashi Iwai };
2022c30aa7b2STakashi Iwai 
2023c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2024c30aa7b2STakashi Iwai {
2025c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2026c30aa7b2STakashi Iwai 
2027c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2028c30aa7b2STakashi Iwai 		return 0;
2029c30aa7b2STakashi Iwai 	if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
2030c30aa7b2STakashi Iwai 	      spec->aamix_out_paths[2]))
2031c30aa7b2STakashi Iwai 		return 0;
2032c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2033c30aa7b2STakashi Iwai 		return -ENOMEM;
2034c30aa7b2STakashi Iwai 	return 0;
2035c30aa7b2STakashi Iwai }
2036c30aa7b2STakashi Iwai 
2037c30aa7b2STakashi Iwai /*
2038352f7f91STakashi Iwai  * shared headphone/mic handling
2039352f7f91STakashi Iwai  */
2040352f7f91STakashi Iwai 
2041352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2042352f7f91STakashi Iwai 
2043352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2044352f7f91STakashi Iwai static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
2045352f7f91STakashi Iwai {
2046352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2047352f7f91STakashi Iwai 	unsigned int val;
2048352f7f91STakashi Iwai 	hda_nid_t pin = spec->autocfg.inputs[1].pin;
2049352f7f91STakashi Iwai 	/* NOTE: this assumes that there are only two inputs, the
2050352f7f91STakashi Iwai 	 * first is the real internal mic and the second is HP/mic jack.
2051352f7f91STakashi Iwai 	 */
2052352f7f91STakashi Iwai 
2053352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2054352f7f91STakashi Iwai 
2055352f7f91STakashi Iwai 	/* This pin does not have vref caps - let's enable vref on pin 0x18
2056352f7f91STakashi Iwai 	   instead, as suggested by Realtek */
2057352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2058352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2059352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2060352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
20617594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
20627594aa33STakashi Iwai 					PIN_IN | (set_as_mic ? vref_val : 0));
2063352f7f91STakashi Iwai 	}
2064352f7f91STakashi Iwai 
2065352f7f91STakashi Iwai 	val = set_as_mic ? val | PIN_IN : PIN_HP;
20662c12c30dSTakashi Iwai 	set_pin_target(codec, pin, val, true);
2067352f7f91STakashi Iwai 
2068352f7f91STakashi Iwai 	spec->automute_speaker = !set_as_mic;
2069352f7f91STakashi Iwai 	call_update_outputs(codec);
2070352f7f91STakashi Iwai }
2071352f7f91STakashi Iwai 
2072352f7f91STakashi Iwai /* create a shared input with the headphone out */
2073352f7f91STakashi Iwai static int create_shared_input(struct hda_codec *codec)
2074352f7f91STakashi Iwai {
2075352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2076352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2077352f7f91STakashi Iwai 	unsigned int defcfg;
2078352f7f91STakashi Iwai 	hda_nid_t nid;
2079352f7f91STakashi Iwai 
2080352f7f91STakashi Iwai 	/* only one internal input pin? */
2081352f7f91STakashi Iwai 	if (cfg->num_inputs != 1)
2082352f7f91STakashi Iwai 		return 0;
2083352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2084352f7f91STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2085352f7f91STakashi Iwai 		return 0;
2086352f7f91STakashi Iwai 
2087352f7f91STakashi Iwai 	if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
2088352f7f91STakashi Iwai 		nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
2089352f7f91STakashi Iwai 	else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
2090352f7f91STakashi Iwai 		nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
2091352f7f91STakashi Iwai 	else
2092352f7f91STakashi Iwai 		return 0; /* both not available */
2093352f7f91STakashi Iwai 
2094352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2095352f7f91STakashi Iwai 		return 0; /* no input */
2096352f7f91STakashi Iwai 
2097352f7f91STakashi Iwai 	cfg->inputs[1].pin = nid;
2098352f7f91STakashi Iwai 	cfg->inputs[1].type = AUTO_PIN_MIC;
2099352f7f91STakashi Iwai 	cfg->num_inputs = 2;
2100352f7f91STakashi Iwai 	spec->shared_mic_hp = 1;
2101352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable shared I/O jack on NID 0x%x\n", nid);
2102352f7f91STakashi Iwai 	return 0;
2103352f7f91STakashi Iwai }
2104352f7f91STakashi Iwai 
2105978e77e7STakashi Iwai /*
2106978e77e7STakashi Iwai  * output jack mode
2107978e77e7STakashi Iwai  */
2108978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2109978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2110978e77e7STakashi Iwai {
2111978e77e7STakashi Iwai 	static const char * const texts[] = {
2112978e77e7STakashi Iwai 		"Line Out", "Headphone Out",
2113978e77e7STakashi Iwai 	};
2114978e77e7STakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts);
2115978e77e7STakashi Iwai }
2116978e77e7STakashi Iwai 
2117978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2118978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2119978e77e7STakashi Iwai {
2120978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2121978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2122978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2123978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2124978e77e7STakashi Iwai 	else
2125978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2126978e77e7STakashi Iwai 	return 0;
2127978e77e7STakashi Iwai }
2128978e77e7STakashi Iwai 
2129978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2130978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2131978e77e7STakashi Iwai {
2132978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2133978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2134978e77e7STakashi Iwai 	unsigned int val;
2135978e77e7STakashi Iwai 
2136978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2137978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2138978e77e7STakashi Iwai 		return 0;
2139978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2140978e77e7STakashi Iwai 	return 1;
2141978e77e7STakashi Iwai }
2142978e77e7STakashi Iwai 
2143978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2144978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2145978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2146978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2147978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2148978e77e7STakashi Iwai };
2149978e77e7STakashi Iwai 
2150978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2151978e77e7STakashi Iwai {
2152978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2153978e77e7STakashi Iwai 	int i;
2154978e77e7STakashi Iwai 
2155978e77e7STakashi Iwai 	for (i = 0; i < spec->kctls.used; i++) {
2156978e77e7STakashi Iwai 		struct snd_kcontrol_new *kctl = snd_array_elem(&spec->kctls, i);
2157978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2158978e77e7STakashi Iwai 			return true;
2159978e77e7STakashi Iwai 	}
2160978e77e7STakashi Iwai 	return false;
2161978e77e7STakashi Iwai }
2162978e77e7STakashi Iwai 
2163978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2164978e77e7STakashi Iwai 			       char *name, size_t name_len)
2165978e77e7STakashi Iwai {
2166978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2167978e77e7STakashi Iwai 	int idx = 0;
2168978e77e7STakashi Iwai 
2169978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2170978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2171978e77e7STakashi Iwai 
2172978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2173978e77e7STakashi Iwai 		;
2174978e77e7STakashi Iwai }
2175978e77e7STakashi Iwai 
2176978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2177978e77e7STakashi Iwai 				 hda_nid_t *pins)
2178978e77e7STakashi Iwai {
2179978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2180978e77e7STakashi Iwai 	int i;
2181978e77e7STakashi Iwai 
2182978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2183978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2184978e77e7STakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2185978e77e7STakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV)) {
2186978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2187978e77e7STakashi Iwai 			char name[44];
2188978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2189978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2190978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2191978e77e7STakashi Iwai 			if (!knew)
2192978e77e7STakashi Iwai 				return -ENOMEM;
2193978e77e7STakashi Iwai 			knew->private_value = pin;
2194978e77e7STakashi Iwai 		}
2195978e77e7STakashi Iwai 	}
2196978e77e7STakashi Iwai 
2197978e77e7STakashi Iwai 	return 0;
2198978e77e7STakashi Iwai }
2199978e77e7STakashi Iwai 
220029476558STakashi Iwai /*
220129476558STakashi Iwai  * input jack mode
220229476558STakashi Iwai  */
220329476558STakashi Iwai 
220429476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
220529476558STakashi Iwai #define NUM_VREFS	6
220629476558STakashi Iwai 
220729476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
220829476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
220929476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
221029476558STakashi Iwai };
221129476558STakashi Iwai 
221229476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
221329476558STakashi Iwai {
221429476558STakashi Iwai 	unsigned int pincap;
221529476558STakashi Iwai 
221629476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
221729476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
221829476558STakashi Iwai 	/* filter out unusual vrefs */
221929476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
222029476558STakashi Iwai 	return pincap;
222129476558STakashi Iwai }
222229476558STakashi Iwai 
222329476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
222429476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
222529476558STakashi Iwai {
222629476558STakashi Iwai 	unsigned int i, n = 0;
222729476558STakashi Iwai 
222829476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
222929476558STakashi Iwai 		if (vref_caps & (1 << i)) {
223029476558STakashi Iwai 			if (n == item_idx)
223129476558STakashi Iwai 				return i;
223229476558STakashi Iwai 			n++;
223329476558STakashi Iwai 		}
223429476558STakashi Iwai 	}
223529476558STakashi Iwai 	return 0;
223629476558STakashi Iwai }
223729476558STakashi Iwai 
223829476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
223929476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
224029476558STakashi Iwai {
224129476558STakashi Iwai 	unsigned int i, n = 0;
224229476558STakashi Iwai 
224329476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
224429476558STakashi Iwai 		if (i == idx)
224529476558STakashi Iwai 			return n;
224629476558STakashi Iwai 		if (vref_caps & (1 << i))
224729476558STakashi Iwai 			n++;
224829476558STakashi Iwai 	}
224929476558STakashi Iwai 	return 0;
225029476558STakashi Iwai }
225129476558STakashi Iwai 
225229476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
225329476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
225429476558STakashi Iwai {
225529476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
225629476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
225729476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
225829476558STakashi Iwai 
225929476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
226029476558STakashi Iwai 				 vref_texts);
226129476558STakashi Iwai 	/* set the right text */
226229476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
226329476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
226429476558STakashi Iwai 	return 0;
226529476558STakashi Iwai }
226629476558STakashi Iwai 
226729476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
226829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
226929476558STakashi Iwai {
227029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
227129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
227229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
227329476558STakashi Iwai 	unsigned int idx;
227429476558STakashi Iwai 
227529476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
227629476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
227729476558STakashi Iwai 	return 0;
227829476558STakashi Iwai }
227929476558STakashi Iwai 
228029476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
228129476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
228229476558STakashi Iwai {
228329476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
228429476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
228529476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
228629476558STakashi Iwai 	unsigned int val, idx;
228729476558STakashi Iwai 
228829476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
228929476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
229029476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
229129476558STakashi Iwai 		return 0;
229229476558STakashi Iwai 
229329476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
229429476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
229529476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
229629476558STakashi Iwai 	return 1;
229729476558STakashi Iwai }
229829476558STakashi Iwai 
229929476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
230029476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
230129476558STakashi Iwai 	.info = in_jack_mode_info,
230229476558STakashi Iwai 	.get = in_jack_mode_get,
230329476558STakashi Iwai 	.put = in_jack_mode_put,
230429476558STakashi Iwai };
230529476558STakashi Iwai 
230629476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
230729476558STakashi Iwai {
230829476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
230929476558STakashi Iwai 	unsigned int defcfg;
231029476558STakashi Iwai 	struct snd_kcontrol_new *knew;
231129476558STakashi Iwai 	char name[44];
231229476558STakashi Iwai 
231329476558STakashi Iwai 	/* no jack mode for fixed pins */
231429476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
231529476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
231629476558STakashi Iwai 		return 0;
231729476558STakashi Iwai 
231829476558STakashi Iwai 	/* no multiple vref caps? */
231929476558STakashi Iwai 	if (hweight32(get_vref_caps(codec, pin)) <= 1)
232029476558STakashi Iwai 		return 0;
232129476558STakashi Iwai 
232229476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
232329476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
232429476558STakashi Iwai 	if (!knew)
232529476558STakashi Iwai 		return -ENOMEM;
232629476558STakashi Iwai 	knew->private_value = pin;
232729476558STakashi Iwai 	return 0;
232829476558STakashi Iwai }
232929476558STakashi Iwai 
2330352f7f91STakashi Iwai 
2331352f7f91STakashi Iwai /*
2332352f7f91STakashi Iwai  * Parse input paths
2333352f7f91STakashi Iwai  */
2334352f7f91STakashi Iwai 
2335352f7f91STakashi Iwai #ifdef CONFIG_PM
2336352f7f91STakashi Iwai /* add the powersave loopback-list entry */
2337352f7f91STakashi Iwai static void add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
2338352f7f91STakashi Iwai {
2339352f7f91STakashi Iwai 	struct hda_amp_list *list;
2340352f7f91STakashi Iwai 
2341352f7f91STakashi Iwai 	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
2342352f7f91STakashi Iwai 		return;
2343352f7f91STakashi Iwai 	list = spec->loopback_list + spec->num_loopbacks;
2344352f7f91STakashi Iwai 	list->nid = mix;
2345352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
2346352f7f91STakashi Iwai 	list->idx = idx;
2347352f7f91STakashi Iwai 	spec->num_loopbacks++;
2348cb53c626STakashi Iwai 	spec->loopback.amplist = spec->loopback_list;
2349cb53c626STakashi Iwai }
2350cb53c626STakashi Iwai #else
2351352f7f91STakashi Iwai #define add_loopback_list(spec, mix, idx) /* NOP */
2352cb53c626STakashi Iwai #endif
2353cb53c626STakashi Iwai 
2354352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
2355196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
2356196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
2357352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
23581da177e4SLinus Torvalds {
2359352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2360352f7f91STakashi Iwai 	struct nid_path *path;
2361352f7f91STakashi Iwai 	unsigned int val;
2362352f7f91STakashi Iwai 	int err, idx;
23631da177e4SLinus Torvalds 
2364352f7f91STakashi Iwai 	if (!nid_has_volume(codec, mix_nid, HDA_INPUT) &&
2365352f7f91STakashi Iwai 	    !nid_has_mute(codec, mix_nid, HDA_INPUT))
2366352f7f91STakashi Iwai 		return 0; /* no need for analog loopback */
2367352f7f91STakashi Iwai 
23683ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
2369352f7f91STakashi Iwai 	if (!path)
2370352f7f91STakashi Iwai 		return -EINVAL;
23710c8c0f56STakashi Iwai 	print_nid_path("loopback", path);
2372196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
2373352f7f91STakashi Iwai 
2374352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
2375352f7f91STakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT)) {
2376352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2377352f7f91STakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val);
2378d13bd412STakashi Iwai 		if (err < 0)
23791da177e4SLinus Torvalds 			return err;
2380352f7f91STakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = val;
23811da177e4SLinus Torvalds 	}
23821da177e4SLinus Torvalds 
2383352f7f91STakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT)) {
2384352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
2385352f7f91STakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val);
2386d13bd412STakashi Iwai 		if (err < 0)
23871da177e4SLinus Torvalds 			return err;
2388352f7f91STakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = val;
23891da177e4SLinus Torvalds 	}
23901da177e4SLinus Torvalds 
2391352f7f91STakashi Iwai 	path->active = true;
2392352f7f91STakashi Iwai 	add_loopback_list(spec, mix_nid, idx);
2393352f7f91STakashi Iwai 	return 0;
23941da177e4SLinus Torvalds }
23951da177e4SLinus Torvalds 
2396352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
23971da177e4SLinus Torvalds {
2398352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
2399352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
2400352f7f91STakashi Iwai }
2401352f7f91STakashi Iwai 
2402352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
2403352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
2404352f7f91STakashi Iwai {
2405352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2406352f7f91STakashi Iwai 	hda_nid_t nid;
2407352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
2408352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
2409352f7f91STakashi Iwai 	int i, nums = 0;
2410352f7f91STakashi Iwai 
2411352f7f91STakashi Iwai 	nid = codec->start_nid;
2412352f7f91STakashi Iwai 	for (i = 0; i < codec->num_nodes; i++, nid++) {
2413352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
2414352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
2415352f7f91STakashi Iwai 
2416352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
2417352f7f91STakashi Iwai 			continue;
2418352f7f91STakashi Iwai 		adc_nids[nums] = nid;
2419352f7f91STakashi Iwai 		if (++nums >= max_nums)
2420352f7f91STakashi Iwai 			break;
2421352f7f91STakashi Iwai 	}
2422352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
24230ffd534eSTakashi Iwai 
24240ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
24250ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
24260ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
24270ffd534eSTakashi Iwai 
2428352f7f91STakashi Iwai 	return nums;
2429352f7f91STakashi Iwai }
2430352f7f91STakashi Iwai 
2431352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
2432352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
2433352f7f91STakashi Iwai  */
2434352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
2435352f7f91STakashi Iwai {
2436352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2437352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
24383a65bcdcSTakashi Iwai 	unsigned int ok_bits;
2439352f7f91STakashi Iwai 	int i, n, nums;
2440352f7f91STakashi Iwai 
2441352f7f91STakashi Iwai  again:
2442352f7f91STakashi Iwai 	nums = 0;
24433a65bcdcSTakashi Iwai 	ok_bits = 0;
2444352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
2445352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
24463a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
2447352f7f91STakashi Iwai 				break;
2448352f7f91STakashi Iwai 		}
24493a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
24503a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
24513a65bcdcSTakashi Iwai 			nums++;
24523a65bcdcSTakashi Iwai 		}
2453352f7f91STakashi Iwai 	}
2454352f7f91STakashi Iwai 
24553a65bcdcSTakashi Iwai 	if (!ok_bits) {
2456352f7f91STakashi Iwai 		if (spec->shared_mic_hp) {
2457352f7f91STakashi Iwai 			spec->shared_mic_hp = 0;
2458352f7f91STakashi Iwai 			imux->num_items = 1;
2459352f7f91STakashi Iwai 			goto again;
2460352f7f91STakashi Iwai 		}
2461352f7f91STakashi Iwai 
2462352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
2463352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
2464352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
24653a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
2466352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
2467352f7f91STakashi Iwai 					break;
2468352f7f91STakashi Iwai 				}
2469352f7f91STakashi Iwai 			}
2470352f7f91STakashi Iwai 		}
2471352f7f91STakashi Iwai 
2472352f7f91STakashi Iwai 		snd_printdd("hda-codec: enabling ADC switching\n");
2473352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
2474352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
24753a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
24763a65bcdcSTakashi Iwai 		nums = 0;
24773a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
24783a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
24793a65bcdcSTakashi Iwai 				continue;
24803a65bcdcSTakashi Iwai 			if (n != nums) {
24813a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
2482980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
2483980428ceSTakashi Iwai 					invalidate_nid_path(codec,
2484980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
24853a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
24863a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
24873a65bcdcSTakashi Iwai 				}
2488980428ceSTakashi Iwai 			}
24893a65bcdcSTakashi Iwai 			nums++;
24903a65bcdcSTakashi Iwai 		}
2491352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
2492352f7f91STakashi Iwai 	}
2493352f7f91STakashi Iwai 
2494352f7f91STakashi Iwai 	if (imux->num_items == 1 || spec->shared_mic_hp) {
2495352f7f91STakashi Iwai 		snd_printdd("hda-codec: reducing to a single ADC\n");
2496352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
2497352f7f91STakashi Iwai 	}
2498352f7f91STakashi Iwai 
2499352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
2500352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
2501352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
2502352f7f91STakashi Iwai 
25031da177e4SLinus Torvalds 	return 0;
25041da177e4SLinus Torvalds }
25051da177e4SLinus Torvalds 
2506f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
2507f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
25089dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
25099dba205bSTakashi Iwai 				const char *label, int anchor)
2510f3fc0b0bSTakashi Iwai {
2511f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2512f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2513f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
2514f3fc0b0bSTakashi Iwai 	bool imux_added = false;
2515f3fc0b0bSTakashi Iwai 	int c;
2516f3fc0b0bSTakashi Iwai 
2517f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
2518f3fc0b0bSTakashi Iwai 		struct nid_path *path;
2519f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
2520f3fc0b0bSTakashi Iwai 
2521f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
2522f3fc0b0bSTakashi Iwai 			continue;
2523f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
2524f3fc0b0bSTakashi Iwai 		if (!path)
2525f3fc0b0bSTakashi Iwai 			continue;
2526f3fc0b0bSTakashi Iwai 		print_nid_path("input", path);
2527f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
2528f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
2529f3fc0b0bSTakashi Iwai 
2530f3fc0b0bSTakashi Iwai 		if (!imux_added) {
2531f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
25329dba205bSTakashi Iwai 			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
2533f3fc0b0bSTakashi Iwai 			imux_added = true;
2534f3fc0b0bSTakashi Iwai 		}
2535f3fc0b0bSTakashi Iwai 	}
2536f3fc0b0bSTakashi Iwai 
2537f3fc0b0bSTakashi Iwai 	return 0;
2538f3fc0b0bSTakashi Iwai }
2539f3fc0b0bSTakashi Iwai 
25401da177e4SLinus Torvalds /*
2541352f7f91STakashi Iwai  * create playback/capture controls for input pins
25421da177e4SLinus Torvalds  */
25439dba205bSTakashi Iwai 
2544c970042cSTakashi Iwai /* fill the label for each input at first */
2545c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
2546c970042cSTakashi Iwai {
2547c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2548c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2549c970042cSTakashi Iwai 	int i;
2550c970042cSTakashi Iwai 
2551c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2552c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
2553c970042cSTakashi Iwai 		const char *label;
2554c970042cSTakashi Iwai 		int j, idx;
2555c970042cSTakashi Iwai 
2556c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
2557c970042cSTakashi Iwai 			continue;
2558c970042cSTakashi Iwai 
2559c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
2560c970042cSTakashi Iwai 		idx = 0;
25618e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
2562c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
2563c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
2564c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
2565c970042cSTakashi Iwai 				break;
2566c970042cSTakashi Iwai 			}
2567c970042cSTakashi Iwai 		}
2568c970042cSTakashi Iwai 
2569c970042cSTakashi Iwai 		spec->input_labels[i] = label;
2570c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
2571c970042cSTakashi Iwai 	}
2572c970042cSTakashi Iwai 
2573c970042cSTakashi Iwai 	return 0;
2574c970042cSTakashi Iwai }
2575c970042cSTakashi Iwai 
25769dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
25779dba205bSTakashi Iwai 
2578352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
2579a7da6ce5STakashi Iwai {
2580352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2581352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2582352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
2583352f7f91STakashi Iwai 	int num_adcs;
2584c970042cSTakashi Iwai 	int i, err;
25852c12c30dSTakashi Iwai 	unsigned int val;
2586a7da6ce5STakashi Iwai 
2587352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
2588352f7f91STakashi Iwai 	if (num_adcs < 0)
2589352f7f91STakashi Iwai 		return 0;
2590352f7f91STakashi Iwai 
2591c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
2592c970042cSTakashi Iwai 	if (err < 0)
2593c970042cSTakashi Iwai 		return err;
2594c970042cSTakashi Iwai 
2595352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2596352f7f91STakashi Iwai 		hda_nid_t pin;
2597352f7f91STakashi Iwai 
2598352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
2599352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
2600352f7f91STakashi Iwai 			continue;
2601352f7f91STakashi Iwai 
26022c12c30dSTakashi Iwai 		val = PIN_IN;
26032c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
26042c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
26052c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, false);
26062c12c30dSTakashi Iwai 
2607352f7f91STakashi Iwai 		if (mixer) {
2608352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
2609196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
2610c970042cSTakashi Iwai 						       spec->input_labels[i],
2611c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
2612c970042cSTakashi Iwai 						       mixer);
2613a7da6ce5STakashi Iwai 				if (err < 0)
2614a7da6ce5STakashi Iwai 					return err;
2615a7da6ce5STakashi Iwai 			}
2616352f7f91STakashi Iwai 		}
2617352f7f91STakashi Iwai 
2618c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
2619c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
2620f3fc0b0bSTakashi Iwai 		if (err < 0)
2621f3fc0b0bSTakashi Iwai 			return err;
262229476558STakashi Iwai 
262329476558STakashi Iwai 		if (spec->add_in_jack_modes) {
262429476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
262529476558STakashi Iwai 			if (err < 0)
262629476558STakashi Iwai 				return err;
262729476558STakashi Iwai 		}
2628352f7f91STakashi Iwai 	}
2629f3fc0b0bSTakashi Iwai 
2630f3fc0b0bSTakashi Iwai 	if (mixer && spec->add_stereo_mix_input) {
26319dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
2632f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
2633f3fc0b0bSTakashi Iwai 		if (err < 0)
2634f3fc0b0bSTakashi Iwai 			return err;
2635352f7f91STakashi Iwai 	}
2636352f7f91STakashi Iwai 
2637a7da6ce5STakashi Iwai 	return 0;
2638a7da6ce5STakashi Iwai }
2639a7da6ce5STakashi Iwai 
26401da177e4SLinus Torvalds 
2641352f7f91STakashi Iwai /*
2642352f7f91STakashi Iwai  * input source mux
2643352f7f91STakashi Iwai  */
2644352f7f91STakashi Iwai 
2645c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
2646c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
2647352f7f91STakashi Iwai {
2648352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2649b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
2650b56fa1edSDavid Henningsson 		snd_BUG();
2651b56fa1edSDavid Henningsson 		return NULL;
2652b56fa1edSDavid Henningsson 	}
2653352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
2654352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
2655d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
2656b56fa1edSDavid Henningsson 		snd_BUG();
2657b56fa1edSDavid Henningsson 		return NULL;
2658b56fa1edSDavid Henningsson 	}
2659c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
266097ec558aSTakashi Iwai }
2661352f7f91STakashi Iwai 
2662352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
2663352f7f91STakashi Iwai 		      unsigned int idx);
2664352f7f91STakashi Iwai 
2665352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
2666352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
2667352f7f91STakashi Iwai {
2668352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2669352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2670352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
2671352f7f91STakashi Iwai }
2672352f7f91STakashi Iwai 
2673352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
2674352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
2675352f7f91STakashi Iwai {
2676352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2677352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2678a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2679352f7f91STakashi Iwai 
2680352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
26811da177e4SLinus Torvalds 	return 0;
26821da177e4SLinus Torvalds }
26831da177e4SLinus Torvalds 
2684352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
2685352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
26861da177e4SLinus Torvalds {
2687352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2688a053d1e3SDavid Henningsson 	unsigned int adc_idx = kcontrol->id.index;
2689352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
2690352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
2691352f7f91STakashi Iwai }
2692352f7f91STakashi Iwai 
2693352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
26941da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2695352f7f91STakashi Iwai 	.name = "Input Source",
2696352f7f91STakashi Iwai 	.info = mux_enum_info,
2697352f7f91STakashi Iwai 	.get = mux_enum_get,
2698352f7f91STakashi Iwai 	.put = mux_enum_put,
26991da177e4SLinus Torvalds };
2700071c73adSTakashi Iwai 
270147d46abbSTakashi Iwai /*
270247d46abbSTakashi Iwai  * capture volume and capture switch ctls
270347d46abbSTakashi Iwai  */
270447d46abbSTakashi Iwai 
2705352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
2706352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
2707071c73adSTakashi Iwai 
270847d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
2709352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
2710352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
2711352f7f91STakashi Iwai 			  put_call_t func, int type)
2712352f7f91STakashi Iwai {
2713352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2714352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2715352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
2716352f7f91STakashi Iwai 	struct nid_path *path;
2717352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
2718071c73adSTakashi Iwai 
2719352f7f91STakashi Iwai 	imux = &spec->input_mux;
2720a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
2721352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
272247d46abbSTakashi Iwai 	/* we use the cache-only update at first since multiple input paths
272347d46abbSTakashi Iwai 	 * may shared the same amp; by updating only caches, the redundant
272447d46abbSTakashi Iwai 	 * writes to hardware can be reduced.
272547d46abbSTakashi Iwai 	 */
2726352f7f91STakashi Iwai 	codec->cached_write = 1;
2727352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2728c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
2729c697b716STakashi Iwai 		if (!path || !path->ctls[type])
2730352f7f91STakashi Iwai 			continue;
2731352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
2732352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
2733352f7f91STakashi Iwai 		if (err < 0)
2734352f7f91STakashi Iwai 			goto error;
2735352f7f91STakashi Iwai 	}
2736352f7f91STakashi Iwai  error:
2737352f7f91STakashi Iwai 	codec->cached_write = 0;
2738352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
273947d46abbSTakashi Iwai 	snd_hda_codec_flush_amp_cache(codec); /* flush the updates */
2740352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
2741a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
2742352f7f91STakashi Iwai 	return err;
2743352f7f91STakashi Iwai }
2744352f7f91STakashi Iwai 
2745352f7f91STakashi Iwai /* capture volume ctl callbacks */
2746352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
2747352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
2748352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
2749352f7f91STakashi Iwai 
2750352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
2751352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2752352f7f91STakashi Iwai {
2753352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2754352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
2755352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
2756352f7f91STakashi Iwai }
2757352f7f91STakashi Iwai 
2758352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
2759352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2760352f7f91STakashi Iwai 	.name = "Capture Volume",
2761352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
2762352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
2763352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
2764352f7f91STakashi Iwai 	.info = cap_vol_info,
2765352f7f91STakashi Iwai 	.get = cap_vol_get,
2766352f7f91STakashi Iwai 	.put = cap_vol_put,
2767352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
2768352f7f91STakashi Iwai };
2769352f7f91STakashi Iwai 
2770352f7f91STakashi Iwai /* capture switch ctl callbacks */
2771352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
2772352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
2773352f7f91STakashi Iwai 
2774352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
2775352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
2776352f7f91STakashi Iwai {
2777a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
2778352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
2779352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
2780352f7f91STakashi Iwai }
2781352f7f91STakashi Iwai 
2782352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
2783352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2784352f7f91STakashi Iwai 	.name = "Capture Switch",
2785352f7f91STakashi Iwai 	.info = cap_sw_info,
2786352f7f91STakashi Iwai 	.get = cap_sw_get,
2787352f7f91STakashi Iwai 	.put = cap_sw_put,
2788352f7f91STakashi Iwai };
2789352f7f91STakashi Iwai 
2790352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
2791352f7f91STakashi Iwai {
2792352f7f91STakashi Iwai 	hda_nid_t nid;
2793352f7f91STakashi Iwai 	int i, depth;
2794352f7f91STakashi Iwai 
2795352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
2796352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
2797352f7f91STakashi Iwai 		if (depth >= path->depth)
2798352f7f91STakashi Iwai 			return -EINVAL;
2799352f7f91STakashi Iwai 		i = path->depth - depth - 1;
2800352f7f91STakashi Iwai 		nid = path->path[i];
2801352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
2802352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
2803352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2804352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2805352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
2806352f7f91STakashi Iwai 				int idx = path->idx[i];
2807352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2808352f7f91STakashi Iwai 					idx = 0;
2809352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
2810352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2811352f7f91STakashi Iwai 			}
2812352f7f91STakashi Iwai 		}
2813352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
2814352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
2815352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2816352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
2817352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
2818352f7f91STakashi Iwai 				int idx = path->idx[i];
2819352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
2820352f7f91STakashi Iwai 					idx = 0;
2821352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
2822352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
2823352f7f91STakashi Iwai 			}
2824352f7f91STakashi Iwai 		}
2825352f7f91STakashi Iwai 	}
2826352f7f91STakashi Iwai 	return 0;
2827352f7f91STakashi Iwai }
2828352f7f91STakashi Iwai 
2829352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
2830352f7f91STakashi Iwai {
2831352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2832352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2833352f7f91STakashi Iwai 	unsigned int val;
2834352f7f91STakashi Iwai 	int i;
2835352f7f91STakashi Iwai 
2836352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
2837352f7f91STakashi Iwai 		return false;
2838352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
2839352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
2840352f7f91STakashi Iwai 			continue;
2841352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
2842352f7f91STakashi Iwai 			return false;
2843352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
2844352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
2845352f7f91STakashi Iwai 	}
2846352f7f91STakashi Iwai 	return false;
2847352f7f91STakashi Iwai }
2848352f7f91STakashi Iwai 
2849a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
2850a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
2851a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2852a35bd1e3STakashi Iwai {
2853a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2854a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2855a35bd1e3STakashi Iwai 	int ret;
2856a35bd1e3STakashi Iwai 
2857a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
2858a35bd1e3STakashi Iwai 	if (ret < 0)
2859a35bd1e3STakashi Iwai 		return ret;
2860a35bd1e3STakashi Iwai 
2861a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
2862a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, ucontrol);
2863a35bd1e3STakashi Iwai 
2864a35bd1e3STakashi Iwai 	return ret;
2865a35bd1e3STakashi Iwai }
2866a35bd1e3STakashi Iwai 
2867352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
2868352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
2869352f7f91STakashi Iwai 			      bool inv_dmic)
2870352f7f91STakashi Iwai {
2871352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2872352f7f91STakashi Iwai 	char tmpname[44];
2873352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
2874352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
2875352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
2876a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
2877352f7f91STakashi Iwai 
2878352f7f91STakashi Iwai 	if (!ctl)
2879352f7f91STakashi Iwai 		return 0;
2880352f7f91STakashi Iwai 
2881352f7f91STakashi Iwai 	if (label)
2882352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2883352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
2884352f7f91STakashi Iwai 	else
2885352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2886352f7f91STakashi Iwai 			 "Capture %s", sfx);
2887a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
2888352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
2889a35bd1e3STakashi Iwai 	if (!knew)
2890a35bd1e3STakashi Iwai 		return -ENOMEM;
2891a90229e0STakashi Iwai 	if (is_switch)
2892a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
2893a35bd1e3STakashi Iwai 	if (!inv_dmic)
2894a35bd1e3STakashi Iwai 		return 0;
2895352f7f91STakashi Iwai 
2896352f7f91STakashi Iwai 	/* Make independent right kcontrol */
2897352f7f91STakashi Iwai 	if (label)
2898352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2899352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
2900352f7f91STakashi Iwai 	else
2901352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
2902352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
2903a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
2904352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
2905a35bd1e3STakashi Iwai 	if (!knew)
2906a35bd1e3STakashi Iwai 		return -ENOMEM;
2907a90229e0STakashi Iwai 	if (is_switch)
2908a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
2909a35bd1e3STakashi Iwai 	return 0;
2910352f7f91STakashi Iwai }
2911352f7f91STakashi Iwai 
2912352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
2913352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
2914352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
2915352f7f91STakashi Iwai 				     bool inv_dmic)
2916352f7f91STakashi Iwai {
2917352f7f91STakashi Iwai 	int err;
2918352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
2919352f7f91STakashi Iwai 	if (err < 0)
2920352f7f91STakashi Iwai 		return err;
2921352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
2922071c73adSTakashi Iwai 	if (err < 0)
2923071c73adSTakashi Iwai 		return err;
2924071c73adSTakashi Iwai 	return 0;
29251da177e4SLinus Torvalds }
2926071c73adSTakashi Iwai 
2927352f7f91STakashi Iwai /* create bound capture volume and switch controls */
2928352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
2929352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
2930352f7f91STakashi Iwai {
2931352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2932352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
2933352f7f91STakashi Iwai 
2934352f7f91STakashi Iwai 	if (vol_ctl) {
293512c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
2936352f7f91STakashi Iwai 		if (!knew)
2937352f7f91STakashi Iwai 			return -ENOMEM;
2938352f7f91STakashi Iwai 		knew->index = idx;
2939352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
2940352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2941352f7f91STakashi Iwai 	}
2942352f7f91STakashi Iwai 	if (sw_ctl) {
294312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
2944352f7f91STakashi Iwai 		if (!knew)
2945352f7f91STakashi Iwai 			return -ENOMEM;
2946352f7f91STakashi Iwai 		knew->index = idx;
2947352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
2948352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
2949352f7f91STakashi Iwai 	}
2950352f7f91STakashi Iwai 	return 0;
2951352f7f91STakashi Iwai }
2952352f7f91STakashi Iwai 
2953352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
2954352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
2955352f7f91STakashi Iwai {
2956352f7f91STakashi Iwai 	struct nid_path *path;
2957352f7f91STakashi Iwai 	unsigned int ctl;
2958352f7f91STakashi Iwai 	int i;
2959352f7f91STakashi Iwai 
2960c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
2961352f7f91STakashi Iwai 	if (!path)
2962352f7f91STakashi Iwai 		return 0;
2963352f7f91STakashi Iwai 	ctl = path->ctls[type];
2964352f7f91STakashi Iwai 	if (!ctl)
2965352f7f91STakashi Iwai 		return 0;
2966352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
2967c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
2968352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
2969352f7f91STakashi Iwai 			return 0;
2970352f7f91STakashi Iwai 	}
2971352f7f91STakashi Iwai 	return ctl;
2972352f7f91STakashi Iwai }
2973352f7f91STakashi Iwai 
2974352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
2975352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
2976352f7f91STakashi Iwai {
2977352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2978352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
2979c970042cSTakashi Iwai 	int i, err, type;
2980352f7f91STakashi Iwai 
2981352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
2982352f7f91STakashi Iwai 		bool inv_dmic;
2983c970042cSTakashi Iwai 		int idx;
29849dba205bSTakashi Iwai 
2985c970042cSTakashi Iwai 		idx = imux->items[i].index;
2986c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
29879dba205bSTakashi Iwai 			continue;
2988352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
2989352f7f91STakashi Iwai 
2990352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
2991c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
2992c970042cSTakashi Iwai 						 spec->input_labels[idx],
2993c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
2994c970042cSTakashi Iwai 						 type,
2995352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
2996352f7f91STakashi Iwai 						 inv_dmic);
2997d13bd412STakashi Iwai 			if (err < 0)
2998071c73adSTakashi Iwai 				return err;
2999352f7f91STakashi Iwai 		}
3000352f7f91STakashi Iwai 	}
3001071c73adSTakashi Iwai 	return 0;
3002352f7f91STakashi Iwai }
3003071c73adSTakashi Iwai 
3004352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3005352f7f91STakashi Iwai {
3006352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3007352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3008352f7f91STakashi Iwai 	int i, n, nums, err;
3009352f7f91STakashi Iwai 
3010352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3011352f7f91STakashi Iwai 		nums = 1;
3012352f7f91STakashi Iwai 	else
3013352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3014352f7f91STakashi Iwai 
3015352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3016352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3017624d914dSTakashi Iwai 		const char *name;
3018624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3019624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3020352f7f91STakashi Iwai 		if (!knew)
3021352f7f91STakashi Iwai 			return -ENOMEM;
3022352f7f91STakashi Iwai 		knew->count = nums;
3023352f7f91STakashi Iwai 	}
3024352f7f91STakashi Iwai 
3025352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3026352f7f91STakashi Iwai 		bool multi = false;
302799a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3028352f7f91STakashi Iwai 		bool inv_dmic = false;
3029352f7f91STakashi Iwai 		int vol, sw;
3030352f7f91STakashi Iwai 
3031352f7f91STakashi Iwai 		vol = sw = 0;
3032352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3033352f7f91STakashi Iwai 			struct nid_path *path;
3034c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3035352f7f91STakashi Iwai 			if (!path)
3036352f7f91STakashi Iwai 				continue;
3037352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3038352f7f91STakashi Iwai 			if (!vol)
3039352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
304099a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3041352f7f91STakashi Iwai 				multi = true;
304299a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
304399a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
304499a5592dSDavid Henningsson 					multi_cap_vol = true;
304599a5592dSDavid Henningsson 			}
3046352f7f91STakashi Iwai 			if (!sw)
3047352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
304899a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3049352f7f91STakashi Iwai 				multi = true;
305099a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
305199a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
305299a5592dSDavid Henningsson 					multi_cap_vol = true;
305399a5592dSDavid Henningsson 			}
3054352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3055352f7f91STakashi Iwai 				inv_dmic = true;
3056352f7f91STakashi Iwai 		}
3057352f7f91STakashi Iwai 
3058352f7f91STakashi Iwai 		if (!multi)
3059352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3060352f7f91STakashi Iwai 							inv_dmic);
306199a5592dSDavid Henningsson 		else if (!multi_cap_vol)
3062352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3063352f7f91STakashi Iwai 		else
3064352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3065d13bd412STakashi Iwai 		if (err < 0)
3066071c73adSTakashi Iwai 			return err;
3067071c73adSTakashi Iwai 	}
3068071c73adSTakashi Iwai 
30691da177e4SLinus Torvalds 	return 0;
30701da177e4SLinus Torvalds }
30711da177e4SLinus Torvalds 
3072352f7f91STakashi Iwai /*
3073352f7f91STakashi Iwai  * add mic boosts if needed
3074352f7f91STakashi Iwai  */
30756f7c83afSTakashi Iwai 
30766f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
30776f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
30786f7c83afSTakashi Iwai 			    int dir, int idx)
30796f7c83afSTakashi Iwai {
30806f7c83afSTakashi Iwai 	unsigned int step;
30816f7c83afSTakashi Iwai 
30826f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
30836f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
30846f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
30856f7c83afSTakashi Iwai 		return false;
30866f7c83afSTakashi Iwai 
30876f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
30886f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
30896f7c83afSTakashi Iwai 	if (step < 0x20)
30906f7c83afSTakashi Iwai 		return false;
30916f7c83afSTakashi Iwai 	return true;
30926f7c83afSTakashi Iwai }
30936f7c83afSTakashi Iwai 
30946f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
30956f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
30966f7c83afSTakashi Iwai 				       struct nid_path *path)
30976f7c83afSTakashi Iwai {
30986f7c83afSTakashi Iwai 	unsigned int val = 0;
30996f7c83afSTakashi Iwai 	hda_nid_t nid;
31006f7c83afSTakashi Iwai 	int depth;
31016f7c83afSTakashi Iwai 
31026f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
31036f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
31046f7c83afSTakashi Iwai 			break;
31056f7c83afSTakashi Iwai 		nid = path->path[depth];
31066f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
31076f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
31086f7c83afSTakashi Iwai 			break;
31096f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
31106f7c83afSTakashi Iwai 					   path->idx[depth])) {
31116f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
31126f7c83afSTakashi Iwai 						  HDA_INPUT);
31136f7c83afSTakashi Iwai 			break;
31146f7c83afSTakashi Iwai 		}
31156f7c83afSTakashi Iwai 	}
31166f7c83afSTakashi Iwai 
31176f7c83afSTakashi Iwai 	return val;
31186f7c83afSTakashi Iwai }
31196f7c83afSTakashi Iwai 
3120352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3121352f7f91STakashi Iwai {
3122352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3123352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
31246f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3125a35bd1e3STakashi Iwai 	int i;
3126352f7f91STakashi Iwai 
31276f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
31286f7c83afSTakashi Iwai 		return 0;
31296f7c83afSTakashi Iwai 
31306f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3131352f7f91STakashi Iwai 		struct nid_path *path;
3132352f7f91STakashi Iwai 		unsigned int val;
31336f7c83afSTakashi Iwai 		int idx;
31346f7c83afSTakashi Iwai 		char boost_label[44];
3135352f7f91STakashi Iwai 
31366f7c83afSTakashi Iwai 		idx = imux->items[i].index;
31376f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
313802aba550SDavid Henningsson 			continue;
313902aba550SDavid Henningsson 
31406f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
31411799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
31426f7c83afSTakashi Iwai 			continue;
31436f7c83afSTakashi Iwai 
31446f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
31456f7c83afSTakashi Iwai 		if (!path)
31466f7c83afSTakashi Iwai 			continue;
31476f7c83afSTakashi Iwai 
31486f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
31496f7c83afSTakashi Iwai 		if (!val)
31506f7c83afSTakashi Iwai 			continue;
31516f7c83afSTakashi Iwai 
31526f7c83afSTakashi Iwai 		/* create a boost control */
3153352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
31546f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3155a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3156a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3157a35bd1e3STakashi Iwai 			return -ENOMEM;
3158352f7f91STakashi Iwai 
3159352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3160352f7f91STakashi Iwai 	}
3161352f7f91STakashi Iwai 	return 0;
3162352f7f91STakashi Iwai }
3163352f7f91STakashi Iwai 
3164352f7f91STakashi Iwai /*
3165352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3166352f7f91STakashi Iwai  */
3167352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3168352f7f91STakashi Iwai {
3169352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
31700c8c0f56STakashi Iwai 	struct nid_path *path;
3171352f7f91STakashi Iwai 	int i, nums;
31722c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
3173352f7f91STakashi Iwai 
3174352f7f91STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a slave */
3175352f7f91STakashi Iwai 	nums = 0;
3176352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
31772c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
3178352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
3179352f7f91STakashi Iwai 		if (!dig_nid)
3180352f7f91STakashi Iwai 			continue;
31813ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
31820c8c0f56STakashi Iwai 		if (!path)
3183352f7f91STakashi Iwai 			continue;
31840c8c0f56STakashi Iwai 		print_nid_path("digout", path);
3185e1284af7STakashi Iwai 		path->active = true;
3186196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
31872c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
3188352f7f91STakashi Iwai 		if (!nums) {
3189352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
3190352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
3191352f7f91STakashi Iwai 		} else {
3192352f7f91STakashi Iwai 			spec->multiout.slave_dig_outs = spec->slave_dig_outs;
3193352f7f91STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
3194352f7f91STakashi Iwai 			break;
3195352f7f91STakashi Iwai 			spec->slave_dig_outs[nums - 1] = dig_nid;
3196352f7f91STakashi Iwai 		}
3197352f7f91STakashi Iwai 		nums++;
3198352f7f91STakashi Iwai 	}
3199352f7f91STakashi Iwai 
3200352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
32012c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
3202352f7f91STakashi Iwai 		dig_nid = codec->start_nid;
3203352f7f91STakashi Iwai 		for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
3204352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
3205352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
3206352f7f91STakashi Iwai 				continue;
3207352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
3208352f7f91STakashi Iwai 				continue;
32092c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
3210352f7f91STakashi Iwai 			if (path) {
32110c8c0f56STakashi Iwai 				print_nid_path("digin", path);
3212352f7f91STakashi Iwai 				path->active = true;
3213352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
32142430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
32152c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
3216352f7f91STakashi Iwai 				break;
3217352f7f91STakashi Iwai 			}
3218352f7f91STakashi Iwai 		}
3219352f7f91STakashi Iwai 	}
3220352f7f91STakashi Iwai }
3221352f7f91STakashi Iwai 
32221da177e4SLinus Torvalds 
32231da177e4SLinus Torvalds /*
3224352f7f91STakashi Iwai  * input MUX handling
32251da177e4SLinus Torvalds  */
32261da177e4SLinus Torvalds 
3227352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
3228352f7f91STakashi Iwai 
3229352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
3230352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3231352f7f91STakashi Iwai 		      unsigned int idx)
3232352f7f91STakashi Iwai {
3233352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3234352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3235352f7f91STakashi Iwai 	struct nid_path *path;
3236352f7f91STakashi Iwai 
3237352f7f91STakashi Iwai 	imux = &spec->input_mux;
3238352f7f91STakashi Iwai 	if (!imux->num_items)
32391da177e4SLinus Torvalds 		return 0;
32401da177e4SLinus Torvalds 
3241352f7f91STakashi Iwai 	if (idx >= imux->num_items)
3242352f7f91STakashi Iwai 		idx = imux->num_items - 1;
3243352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
3244352f7f91STakashi Iwai 		return 0;
3245352f7f91STakashi Iwai 
3246c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
3247352f7f91STakashi Iwai 	if (!path)
3248352f7f91STakashi Iwai 		return 0;
3249352f7f91STakashi Iwai 	if (path->active)
3250352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, false, false);
3251352f7f91STakashi Iwai 
3252352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
3253352f7f91STakashi Iwai 
3254352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
3255352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
3256352f7f91STakashi Iwai 
3257352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3258352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
3259352f7f91STakashi Iwai 
3260c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
3261352f7f91STakashi Iwai 	if (!path)
3262352f7f91STakashi Iwai 		return 0;
3263352f7f91STakashi Iwai 	if (path->active)
3264352f7f91STakashi Iwai 		return 0;
3265352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
3266352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
3267a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
32681da177e4SLinus Torvalds 	return 1;
32691da177e4SLinus Torvalds }
32701da177e4SLinus Torvalds 
32711da177e4SLinus Torvalds 
32721da177e4SLinus Torvalds /*
3273352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
32741da177e4SLinus Torvalds  */
3275352f7f91STakashi Iwai 
3276352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
3277352f7f91STakashi Iwai static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
32781da177e4SLinus Torvalds {
3279352f7f91STakashi Iwai 	int i, present = 0;
32801da177e4SLinus Torvalds 
3281352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3282352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3283352f7f91STakashi Iwai 		if (!nid)
3284352f7f91STakashi Iwai 			break;
32850b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
32860b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
32870b4df931STakashi Iwai 			continue;
3288352f7f91STakashi Iwai 		present |= snd_hda_jack_detect(codec, nid);
32891da177e4SLinus Torvalds 	}
3290352f7f91STakashi Iwai 	return present;
32911da177e4SLinus Torvalds }
32921da177e4SLinus Torvalds 
3293352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
3294352f7f91STakashi Iwai static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
32952c12c30dSTakashi Iwai 			bool mute)
32961da177e4SLinus Torvalds {
3297352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3298352f7f91STakashi Iwai 	int i;
32991da177e4SLinus Torvalds 
3300352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
3301352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
3302352f7f91STakashi Iwai 		unsigned int val;
3303352f7f91STakashi Iwai 		if (!nid)
3304352f7f91STakashi Iwai 			break;
3305352f7f91STakashi Iwai 		/* don't reset VREF value in case it's controlling
3306352f7f91STakashi Iwai 		 * the amp (see alc861_fixup_asus_amp_vref_0f())
3307352f7f91STakashi Iwai 		 */
33082c12c30dSTakashi Iwai 		if (spec->keep_vref_in_automute)
33092c12c30dSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
33102c12c30dSTakashi Iwai 		else
3311352f7f91STakashi Iwai 			val = 0;
33122c12c30dSTakashi Iwai 		if (!mute)
33132c12c30dSTakashi Iwai 			val |= snd_hda_codec_get_pin_target(codec, nid);
33142c12c30dSTakashi Iwai 		/* here we call update_pin_ctl() so that the pinctl is changed
33152c12c30dSTakashi Iwai 		 * without changing the pinctl target value;
33162c12c30dSTakashi Iwai 		 * the original target value will be still referred at the
33172c12c30dSTakashi Iwai 		 * init / resume again
33182c12c30dSTakashi Iwai 		 */
33192c12c30dSTakashi Iwai 		update_pin_ctl(codec, nid, val);
3320d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
3321352f7f91STakashi Iwai 	}
3322352f7f91STakashi Iwai }
33231da177e4SLinus Torvalds 
3324352f7f91STakashi Iwai /* Toggle outputs muting */
33255d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
3326352f7f91STakashi Iwai {
3327352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3328352f7f91STakashi Iwai 	int on;
3329352f7f91STakashi Iwai 
3330352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
3331352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
3332352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
3333352f7f91STakashi Iwai 	 */
3334352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
3335352f7f91STakashi Iwai 		do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
33362c12c30dSTakashi Iwai 		    spec->autocfg.hp_pins, spec->master_mute);
3337352f7f91STakashi Iwai 
3338352f7f91STakashi Iwai 	if (!spec->automute_speaker)
3339352f7f91STakashi Iwai 		on = 0;
3340352f7f91STakashi Iwai 	else
3341352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
3342352f7f91STakashi Iwai 	on |= spec->master_mute;
334347b9ddb8STakashi Iwai 	spec->speaker_muted = on;
3344352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
33452c12c30dSTakashi Iwai 		    spec->autocfg.speaker_pins, on);
3346352f7f91STakashi Iwai 
3347352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
3348352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
3349352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
3350352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
3351352f7f91STakashi Iwai 		return;
3352352f7f91STakashi Iwai 	if (!spec->automute_lo)
3353352f7f91STakashi Iwai 		on = 0;
3354352f7f91STakashi Iwai 	else
3355352f7f91STakashi Iwai 		on = spec->hp_jack_present;
3356352f7f91STakashi Iwai 	on |= spec->master_mute;
335747b9ddb8STakashi Iwai 	spec->line_out_muted = on;
3358352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
33592c12c30dSTakashi Iwai 		    spec->autocfg.line_out_pins, on);
3360352f7f91STakashi Iwai }
33615d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);
3362352f7f91STakashi Iwai 
3363352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
3364352f7f91STakashi Iwai {
3365352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3366352f7f91STakashi Iwai 	if (spec->automute_hook)
3367352f7f91STakashi Iwai 		spec->automute_hook(codec);
3368352f7f91STakashi Iwai 	else
33695d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
3370352f7f91STakashi Iwai }
3371352f7f91STakashi Iwai 
3372352f7f91STakashi Iwai /* standard HP-automute helper */
33735d550e15STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3374352f7f91STakashi Iwai {
3375352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3376352f7f91STakashi Iwai 
3377352f7f91STakashi Iwai 	spec->hp_jack_present =
3378352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
3379352f7f91STakashi Iwai 			     spec->autocfg.hp_pins);
3380352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
3381352f7f91STakashi Iwai 		return;
3382352f7f91STakashi Iwai 	call_update_outputs(codec);
3383352f7f91STakashi Iwai }
33845d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_hp_automute);
3385352f7f91STakashi Iwai 
3386352f7f91STakashi Iwai /* standard line-out-automute helper */
33875d550e15STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack)
3388352f7f91STakashi Iwai {
3389352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3390352f7f91STakashi Iwai 
3391352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
3392352f7f91STakashi Iwai 		return;
3393352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
3394352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
3395352f7f91STakashi Iwai 		return;
3396352f7f91STakashi Iwai 
3397352f7f91STakashi Iwai 	spec->line_jack_present =
3398352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
3399352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
3400352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
3401352f7f91STakashi Iwai 		return;
3402352f7f91STakashi Iwai 	call_update_outputs(codec);
3403352f7f91STakashi Iwai }
34045d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_line_automute);
3405352f7f91STakashi Iwai 
3406352f7f91STakashi Iwai /* standard mic auto-switch helper */
34075d550e15STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *jack)
3408352f7f91STakashi Iwai {
3409352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3410352f7f91STakashi Iwai 	int i;
3411352f7f91STakashi Iwai 
3412352f7f91STakashi Iwai 	if (!spec->auto_mic)
3413352f7f91STakashi Iwai 		return;
3414352f7f91STakashi Iwai 
3415352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
34160b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
34170b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
34180b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
34190b4df931STakashi Iwai 			continue;
34200b4df931STakashi Iwai 		if (snd_hda_jack_detect(codec, pin)) {
3421352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
3422352f7f91STakashi Iwai 			return;
3423352f7f91STakashi Iwai 		}
3424352f7f91STakashi Iwai 	}
3425352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
34261da177e4SLinus Torvalds }
34275d550e15STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch);
34281da177e4SLinus Torvalds 
3429a5cc2509STakashi Iwai /* update jack retasking */
3430a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec)
3431a5cc2509STakashi Iwai {
3432a5cc2509STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3433a5cc2509STakashi Iwai 
3434a5cc2509STakashi Iwai 	if (spec->hp_automute_hook)
3435a5cc2509STakashi Iwai 		spec->hp_automute_hook(codec, NULL);
3436a5cc2509STakashi Iwai 	else
3437a5cc2509STakashi Iwai 		snd_hda_gen_hp_automute(codec, NULL);
3438a5cc2509STakashi Iwai 	if (spec->line_automute_hook)
3439a5cc2509STakashi Iwai 		spec->line_automute_hook(codec, NULL);
3440a5cc2509STakashi Iwai 	else
3441a5cc2509STakashi Iwai 		snd_hda_gen_line_automute(codec, NULL);
3442a5cc2509STakashi Iwai 	if (spec->mic_autoswitch_hook)
3443a5cc2509STakashi Iwai 		spec->mic_autoswitch_hook(codec, NULL);
3444a5cc2509STakashi Iwai 	else
3445a5cc2509STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, NULL);
3446a5cc2509STakashi Iwai }
3447a5cc2509STakashi Iwai 
34481da177e4SLinus Torvalds /*
3449352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
34501da177e4SLinus Torvalds  */
3451352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
3452352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
3453352f7f91STakashi Iwai {
3454352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3455352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3456352f7f91STakashi Iwai 	static const char * const texts3[] = {
3457352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
34581da177e4SLinus Torvalds 	};
34591da177e4SLinus Torvalds 
3460352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
3461352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
3462352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
3463352f7f91STakashi Iwai }
3464352f7f91STakashi Iwai 
3465352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
3466352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3467352f7f91STakashi Iwai {
3468352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3469352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3470352f7f91STakashi Iwai 	unsigned int val = 0;
3471352f7f91STakashi Iwai 	if (spec->automute_speaker)
3472352f7f91STakashi Iwai 		val++;
3473352f7f91STakashi Iwai 	if (spec->automute_lo)
3474352f7f91STakashi Iwai 		val++;
3475352f7f91STakashi Iwai 
3476352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
3477352f7f91STakashi Iwai 	return 0;
3478352f7f91STakashi Iwai }
3479352f7f91STakashi Iwai 
3480352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
3481352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3482352f7f91STakashi Iwai {
3483352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3484352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3485352f7f91STakashi Iwai 
3486352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
3487352f7f91STakashi Iwai 	case 0:
3488352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
3489352f7f91STakashi Iwai 			return 0;
3490352f7f91STakashi Iwai 		spec->automute_speaker = 0;
3491352f7f91STakashi Iwai 		spec->automute_lo = 0;
3492352f7f91STakashi Iwai 		break;
3493352f7f91STakashi Iwai 	case 1:
3494352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
3495352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
3496352f7f91STakashi Iwai 				return 0;
3497352f7f91STakashi Iwai 			spec->automute_speaker = 1;
3498352f7f91STakashi Iwai 			spec->automute_lo = 0;
3499352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
3500352f7f91STakashi Iwai 			if (spec->automute_lo)
3501352f7f91STakashi Iwai 				return 0;
3502352f7f91STakashi Iwai 			spec->automute_lo = 1;
3503352f7f91STakashi Iwai 		} else
3504352f7f91STakashi Iwai 			return -EINVAL;
3505352f7f91STakashi Iwai 		break;
3506352f7f91STakashi Iwai 	case 2:
3507352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
3508352f7f91STakashi Iwai 			return -EINVAL;
3509352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
3510352f7f91STakashi Iwai 			return 0;
3511352f7f91STakashi Iwai 		spec->automute_speaker = 1;
3512352f7f91STakashi Iwai 		spec->automute_lo = 1;
3513352f7f91STakashi Iwai 		break;
3514352f7f91STakashi Iwai 	default:
3515352f7f91STakashi Iwai 		return -EINVAL;
3516352f7f91STakashi Iwai 	}
3517352f7f91STakashi Iwai 	call_update_outputs(codec);
3518352f7f91STakashi Iwai 	return 1;
3519352f7f91STakashi Iwai }
3520352f7f91STakashi Iwai 
3521352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
3522352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3523352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
3524352f7f91STakashi Iwai 	.info = automute_mode_info,
3525352f7f91STakashi Iwai 	.get = automute_mode_get,
3526352f7f91STakashi Iwai 	.put = automute_mode_put,
3527352f7f91STakashi Iwai };
3528352f7f91STakashi Iwai 
3529352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
3530352f7f91STakashi Iwai {
3531352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3532352f7f91STakashi Iwai 
353312c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
3534352f7f91STakashi Iwai 		return -ENOMEM;
3535352f7f91STakashi Iwai 	return 0;
3536352f7f91STakashi Iwai }
3537352f7f91STakashi Iwai 
3538352f7f91STakashi Iwai /*
3539352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
3540352f7f91STakashi Iwai  * Set up appropriately if really supported
3541352f7f91STakashi Iwai  */
3542352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
3543352f7f91STakashi Iwai {
3544352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3545352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3546352f7f91STakashi Iwai 	int present = 0;
3547352f7f91STakashi Iwai 	int i, err;
3548352f7f91STakashi Iwai 
3549f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
3550f72706beSTakashi Iwai 		return 0;
3551f72706beSTakashi Iwai 
3552352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
3553352f7f91STakashi Iwai 		present++;
3554352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
3555352f7f91STakashi Iwai 		present++;
3556352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
3557352f7f91STakashi Iwai 		present++;
3558352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
3559352f7f91STakashi Iwai 		return 0;
3560352f7f91STakashi Iwai 
3561352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
3562352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
3563352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3564352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3565352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3566352f7f91STakashi Iwai 	}
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
3569352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
3570352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
3571352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
3572352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
3573352f7f91STakashi Iwai 	}
3574352f7f91STakashi Iwai 
3575352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
3576352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
3577352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
3578352f7f91STakashi Iwai 			continue;
3579352f7f91STakashi Iwai 		snd_printdd("hda-codec: Enable HP auto-muting on NID 0x%x\n",
3580352f7f91STakashi Iwai 			    nid);
3581352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid, HDA_GEN_HP_EVENT,
35822e03e952STakashi Iwai 						    spec->hp_automute_hook ?
35832e03e952STakashi Iwai 						    spec->hp_automute_hook :
35845d550e15STakashi Iwai 						    snd_hda_gen_hp_automute);
3585352f7f91STakashi Iwai 		spec->detect_hp = 1;
3586352f7f91STakashi Iwai 	}
3587352f7f91STakashi Iwai 
3588352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
3589352f7f91STakashi Iwai 		if (cfg->speaker_outs)
3590352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
3591352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
3592352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
3593352f7f91STakashi Iwai 					continue;
3594352f7f91STakashi Iwai 				snd_printdd("hda-codec: Enable Line-Out auto-muting on NID 0x%x\n", nid);
3595352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
3596352f7f91STakashi Iwai 								    HDA_GEN_FRONT_EVENT,
35972e03e952STakashi Iwai 								    spec->line_automute_hook ?
35982e03e952STakashi Iwai 								    spec->line_automute_hook :
35995d550e15STakashi Iwai 								    snd_hda_gen_line_automute);
3600352f7f91STakashi Iwai 				spec->detect_lo = 1;
3601352f7f91STakashi Iwai 			}
3602352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
3603352f7f91STakashi Iwai 	}
3604352f7f91STakashi Iwai 
3605352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
3606352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
3607352f7f91STakashi Iwai 
3608352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
3609352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
3610352f7f91STakashi Iwai 
3611352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
3612352f7f91STakashi Iwai 		/* create a control for automute mode */
3613352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
3614352f7f91STakashi Iwai 		if (err < 0)
3615352f7f91STakashi Iwai 			return err;
3616352f7f91STakashi Iwai 	}
3617352f7f91STakashi Iwai 	return 0;
3618352f7f91STakashi Iwai }
3619352f7f91STakashi Iwai 
3620352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
3621352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
3622352f7f91STakashi Iwai {
3623352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3624352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3625352f7f91STakashi Iwai 	int i;
3626352f7f91STakashi Iwai 
3627352f7f91STakashi Iwai 	imux = &spec->input_mux;
3628352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
3629352f7f91STakashi Iwai 		spec->am_entry[i].idx =
3630352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
3631352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
3632352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
3633352f7f91STakashi Iwai 			return false; /* no corresponding imux */
3634352f7f91STakashi Iwai 	}
3635352f7f91STakashi Iwai 
3636352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
3637352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
3638352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
3639352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
3640352f7f91STakashi Iwai 						    HDA_GEN_MIC_EVENT,
36412e03e952STakashi Iwai 						    spec->mic_autoswitch_hook ?
36422e03e952STakashi Iwai 						    spec->mic_autoswitch_hook :
36435d550e15STakashi Iwai 						    snd_hda_gen_mic_autoswitch);
3644352f7f91STakashi Iwai 	return true;
3645352f7f91STakashi Iwai }
3646352f7f91STakashi Iwai 
3647352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
3648352f7f91STakashi Iwai {
3649352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
3650352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
3651352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
3652352f7f91STakashi Iwai }
3653352f7f91STakashi Iwai 
3654352f7f91STakashi Iwai /*
3655352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
3656352f7f91STakashi Iwai  * Set up if really supported
3657352f7f91STakashi Iwai  */
3658352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
3659352f7f91STakashi Iwai {
3660352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3661352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3662352f7f91STakashi Iwai 	unsigned int types;
3663352f7f91STakashi Iwai 	int i, num_pins;
3664352f7f91STakashi Iwai 
3665d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
3666d12daf6fSTakashi Iwai 		return 0;
3667d12daf6fSTakashi Iwai 
3668352f7f91STakashi Iwai 	types = 0;
3669352f7f91STakashi Iwai 	num_pins = 0;
3670352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3671352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
3672352f7f91STakashi Iwai 		unsigned int attr;
3673352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
3674352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
3675352f7f91STakashi Iwai 		if (types & (1 << attr))
3676352f7f91STakashi Iwai 			return 0; /* already occupied */
3677352f7f91STakashi Iwai 		switch (attr) {
3678352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
3679352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
3680352f7f91STakashi Iwai 				return 0; /* invalid type */
3681352f7f91STakashi Iwai 			break;
3682352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
3683352f7f91STakashi Iwai 			return 0; /* invalid entry */
3684352f7f91STakashi Iwai 		default:
3685352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
3686352f7f91STakashi Iwai 				return 0; /* invalid type */
3687352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
3688352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
3689352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
3690352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
3691352f7f91STakashi Iwai 				return 0; /* no unsol support */
3692352f7f91STakashi Iwai 			break;
3693352f7f91STakashi Iwai 		}
3694352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
3695352f7f91STakashi Iwai 			return 0;
3696352f7f91STakashi Iwai 		types |= (1 << attr);
3697352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
3698352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
3699352f7f91STakashi Iwai 		num_pins++;
3700352f7f91STakashi Iwai 	}
3701352f7f91STakashi Iwai 
3702352f7f91STakashi Iwai 	if (num_pins < 2)
3703352f7f91STakashi Iwai 		return 0;
3704352f7f91STakashi Iwai 
3705352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
3706352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
3707352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
3708352f7f91STakashi Iwai 	 */
3709352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
3710352f7f91STakashi Iwai 	     compare_attr, NULL);
3711352f7f91STakashi Iwai 
3712352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
3713352f7f91STakashi Iwai 		return 0;
3714352f7f91STakashi Iwai 
3715352f7f91STakashi Iwai 	spec->auto_mic = 1;
3716352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
3717352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
3718352f7f91STakashi Iwai 	snd_printdd("hda-codec: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
3719352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
3720352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
3721352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
3722352f7f91STakashi Iwai 
3723352f7f91STakashi Iwai 	return 0;
3724352f7f91STakashi Iwai }
3725352f7f91STakashi Iwai 
3726352f7f91STakashi Iwai 
37279eb413e5STakashi Iwai /*
37289eb413e5STakashi Iwai  * Parse the given BIOS configuration and set up the hda_gen_spec
37299eb413e5STakashi Iwai  *
37309eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
3731352f7f91STakashi Iwai  * or a negative error code
3732352f7f91STakashi Iwai  */
3733352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
37349eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
3735352f7f91STakashi Iwai {
3736352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3737352f7f91STakashi Iwai 	int err;
3738352f7f91STakashi Iwai 
37391c70a583STakashi Iwai 	parse_user_hints(codec);
37401c70a583STakashi Iwai 
37419eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
37429eb413e5STakashi Iwai 		spec->autocfg = *cfg;
37439eb413e5STakashi Iwai 		cfg = &spec->autocfg;
37449eb413e5STakashi Iwai 	}
37459eb413e5STakashi Iwai 
37466fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
37476fc4cb97SDavid Henningsson 
3748352f7f91STakashi Iwai 	if (!cfg->line_outs) {
3749352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
3750352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
3751352f7f91STakashi Iwai 			spec->no_analog = 1;
3752352f7f91STakashi Iwai 			goto dig_only;
3753352f7f91STakashi Iwai 		}
3754352f7f91STakashi Iwai 		return 0; /* can't find valid BIOS pin config */
3755352f7f91STakashi Iwai 	}
3756352f7f91STakashi Iwai 
3757352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
3758352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
3759352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
3760352f7f91STakashi Iwai 		/* use HP as primary out */
3761352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
3762352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
3763352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
3764352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
3765352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
3766352f7f91STakashi Iwai 		cfg->hp_outs = 0;
3767352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
3768352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
3769352f7f91STakashi Iwai 	}
3770352f7f91STakashi Iwai 
3771352f7f91STakashi Iwai 	err = parse_output_paths(codec);
3772352f7f91STakashi Iwai 	if (err < 0)
3773352f7f91STakashi Iwai 		return err;
3774352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
3775352f7f91STakashi Iwai 	if (err < 0)
3776352f7f91STakashi Iwai 		return err;
3777352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
3778352f7f91STakashi Iwai 	if (err < 0)
3779352f7f91STakashi Iwai 		return err;
3780352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
3781352f7f91STakashi Iwai 	if (err < 0)
3782352f7f91STakashi Iwai 		return err;
3783352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
3784352f7f91STakashi Iwai 	if (err < 0)
3785352f7f91STakashi Iwai 		return err;
378638cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
378738cf6f1aSTakashi Iwai 	if (err < 0)
378838cf6f1aSTakashi Iwai 		return err;
3789c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
3790c30aa7b2STakashi Iwai 	if (err < 0)
3791c30aa7b2STakashi Iwai 		return err;
3792352f7f91STakashi Iwai 	err = create_shared_input(codec);
3793352f7f91STakashi Iwai 	if (err < 0)
3794352f7f91STakashi Iwai 		return err;
3795352f7f91STakashi Iwai 	err = create_input_ctls(codec);
3796352f7f91STakashi Iwai 	if (err < 0)
3797352f7f91STakashi Iwai 		return err;
3798352f7f91STakashi Iwai 
3799a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
3800a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
3801a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
3802a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3803a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
3804a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
3805a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
3806a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
3807352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
3808352f7f91STakashi Iwai 					  spec->const_channel_count);
3809352f7f91STakashi Iwai 
3810352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
3811352f7f91STakashi Iwai 	if (err < 0)
3812352f7f91STakashi Iwai 		return err;
3813352f7f91STakashi Iwai 
3814352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
3815352f7f91STakashi Iwai 	if (err < 0)
3816352f7f91STakashi Iwai 		return err;
3817352f7f91STakashi Iwai 
3818352f7f91STakashi Iwai 	if (!spec->shared_mic_hp) {
3819352f7f91STakashi Iwai 		err = check_auto_mic_availability(codec);
3820352f7f91STakashi Iwai 		if (err < 0)
3821352f7f91STakashi Iwai 			return err;
3822352f7f91STakashi Iwai 	}
3823352f7f91STakashi Iwai 
3824352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
3825352f7f91STakashi Iwai 	if (err < 0)
3826352f7f91STakashi Iwai 		return err;
3827352f7f91STakashi Iwai 
3828352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
3829352f7f91STakashi Iwai 	if (err < 0)
3830352f7f91STakashi Iwai 		return err;
3831352f7f91STakashi Iwai 
3832978e77e7STakashi Iwai 	if (spec->add_out_jack_modes) {
3833978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
3834978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
3835978e77e7STakashi Iwai 						    cfg->line_out_pins);
3836978e77e7STakashi Iwai 			if (err < 0)
3837978e77e7STakashi Iwai 				return err;
3838978e77e7STakashi Iwai 		}
3839978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
3840978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
3841978e77e7STakashi Iwai 						    cfg->hp_pins);
3842978e77e7STakashi Iwai 			if (err < 0)
3843978e77e7STakashi Iwai 				return err;
3844978e77e7STakashi Iwai 		}
3845978e77e7STakashi Iwai 	}
3846978e77e7STakashi Iwai 
3847352f7f91STakashi Iwai  dig_only:
3848352f7f91STakashi Iwai 	parse_digital(codec);
3849352f7f91STakashi Iwai 
3850352f7f91STakashi Iwai 	return 1;
3851352f7f91STakashi Iwai }
3852352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_parse_auto_config);
3853352f7f91STakashi Iwai 
3854352f7f91STakashi Iwai 
3855352f7f91STakashi Iwai /*
3856352f7f91STakashi Iwai  * Build control elements
3857352f7f91STakashi Iwai  */
3858352f7f91STakashi Iwai 
3859352f7f91STakashi Iwai /* slave controls for virtual master */
3860352f7f91STakashi Iwai static const char * const slave_pfxs[] = {
3861352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
3862352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
3863352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
3864ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
3865ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
3866ee79c69aSTakashi Iwai 	"Headphone Side",
3867352f7f91STakashi Iwai 	NULL,
3868352f7f91STakashi Iwai };
3869352f7f91STakashi Iwai 
3870352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
3871352f7f91STakashi Iwai {
3872352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3873352f7f91STakashi Iwai 	int err;
3874352f7f91STakashi Iwai 
387536502d02STakashi Iwai 	if (spec->kctls.used) {
3876352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
3877352f7f91STakashi Iwai 		if (err < 0)
3878352f7f91STakashi Iwai 			return err;
387936502d02STakashi Iwai 	}
3880352f7f91STakashi Iwai 
3881352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
3882352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
3883352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3884352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
3885352f7f91STakashi Iwai 						  spec->pcm_rec[1].pcm_type);
3886352f7f91STakashi Iwai 		if (err < 0)
3887352f7f91STakashi Iwai 			return err;
3888352f7f91STakashi Iwai 		if (!spec->no_analog) {
3889352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
3890352f7f91STakashi Iwai 							    &spec->multiout);
3891352f7f91STakashi Iwai 			if (err < 0)
3892352f7f91STakashi Iwai 				return err;
3893352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
3894352f7f91STakashi Iwai 		}
3895352f7f91STakashi Iwai 	}
3896352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
3897352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
3898352f7f91STakashi Iwai 		if (err < 0)
3899352f7f91STakashi Iwai 			return err;
3900352f7f91STakashi Iwai 	}
3901352f7f91STakashi Iwai 
3902352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
3903352f7f91STakashi Iwai 	if (!spec->no_analog &&
3904352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
3905352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
39067a71bbf3STakashi Iwai 					  spec->vmaster_tlv, slave_pfxs,
3907352f7f91STakashi Iwai 					  "Playback Volume");
3908352f7f91STakashi Iwai 		if (err < 0)
3909352f7f91STakashi Iwai 			return err;
3910352f7f91STakashi Iwai 	}
3911352f7f91STakashi Iwai 	if (!spec->no_analog &&
3912352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
3913352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
3914352f7f91STakashi Iwai 					    NULL, slave_pfxs,
3915352f7f91STakashi Iwai 					    "Playback Switch",
3916352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
3917352f7f91STakashi Iwai 		if (err < 0)
3918352f7f91STakashi Iwai 			return err;
3919352f7f91STakashi Iwai 		if (spec->vmaster_mute.hook)
3920fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
3921fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
3922352f7f91STakashi Iwai 	}
3923352f7f91STakashi Iwai 
3924352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
3925352f7f91STakashi Iwai 
3926352f7f91STakashi Iwai 	if (spec->shared_mic_hp) {
3927352f7f91STakashi Iwai 		int err;
3928352f7f91STakashi Iwai 		int nid = spec->autocfg.inputs[1].pin;
3929352f7f91STakashi Iwai 		err = snd_hda_jack_add_kctl(codec, nid, "Headphone Mic", 0);
3930352f7f91STakashi Iwai 		if (err < 0)
3931352f7f91STakashi Iwai 			return err;
3932352f7f91STakashi Iwai 		err = snd_hda_jack_detect_enable(codec, nid, 0);
3933352f7f91STakashi Iwai 		if (err < 0)
3934352f7f91STakashi Iwai 			return err;
3935352f7f91STakashi Iwai 	}
3936352f7f91STakashi Iwai 
3937352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
3938352f7f91STakashi Iwai 	if (err < 0)
3939352f7f91STakashi Iwai 		return err;
3940352f7f91STakashi Iwai 
3941352f7f91STakashi Iwai 	return 0;
3942352f7f91STakashi Iwai }
3943352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_controls);
3944352f7f91STakashi Iwai 
3945352f7f91STakashi Iwai 
3946352f7f91STakashi Iwai /*
3947352f7f91STakashi Iwai  * PCM definitions
3948352f7f91STakashi Iwai  */
3949352f7f91STakashi Iwai 
3950e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
3951e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
3952e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
3953e6b85f3cSTakashi Iwai 				   int action)
3954e6b85f3cSTakashi Iwai {
3955e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3956e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
3957e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
3958e6b85f3cSTakashi Iwai }
3959e6b85f3cSTakashi Iwai 
3960ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
3961ac2e8736STakashi Iwai 				  struct hda_codec *codec,
3962ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
3963ac2e8736STakashi Iwai 				  int action)
3964ac2e8736STakashi Iwai {
3965ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3966ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
3967ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
3968ac2e8736STakashi Iwai }
3969ac2e8736STakashi Iwai 
3970352f7f91STakashi Iwai /*
3971352f7f91STakashi Iwai  * Analog playback callbacks
3972352f7f91STakashi Iwai  */
3973352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
3974352f7f91STakashi Iwai 			     struct hda_codec *codec,
3975352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
3976352f7f91STakashi Iwai {
3977352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
397838cf6f1aSTakashi Iwai 	int err;
397938cf6f1aSTakashi Iwai 
398038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
398138cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
398238cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
3983352f7f91STakashi Iwai 					     hinfo);
3984e6b85f3cSTakashi Iwai 	if (!err) {
398538cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
3986e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
3987e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
3988e6b85f3cSTakashi Iwai 	}
398938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
399038cf6f1aSTakashi Iwai 	return err;
3991352f7f91STakashi Iwai }
3992352f7f91STakashi Iwai 
3993352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
399497ec558aSTakashi Iwai 				struct hda_codec *codec,
399597ec558aSTakashi Iwai 				unsigned int stream_tag,
399697ec558aSTakashi Iwai 				unsigned int format,
399797ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
399897ec558aSTakashi Iwai {
3999352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4000e6b85f3cSTakashi Iwai 	int err;
4001e6b85f3cSTakashi Iwai 
4002e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
4003352f7f91STakashi Iwai 					       stream_tag, format, substream);
4004e6b85f3cSTakashi Iwai 	if (!err)
4005e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4006e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
4007e6b85f3cSTakashi Iwai 	return err;
4008352f7f91STakashi Iwai }
400997ec558aSTakashi Iwai 
4010352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4011352f7f91STakashi Iwai 				struct hda_codec *codec,
4012352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
4013352f7f91STakashi Iwai {
4014352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4015e6b85f3cSTakashi Iwai 	int err;
4016e6b85f3cSTakashi Iwai 
4017e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
4018e6b85f3cSTakashi Iwai 	if (!err)
4019e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
4020e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
4021e6b85f3cSTakashi Iwai 	return err;
4022352f7f91STakashi Iwai }
4023352f7f91STakashi Iwai 
402438cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
402538cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
402638cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
402738cf6f1aSTakashi Iwai {
402838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
402938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
403038cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
4031e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4032e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
403338cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
403438cf6f1aSTakashi Iwai 	return 0;
403538cf6f1aSTakashi Iwai }
403638cf6f1aSTakashi Iwai 
4037ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
4038ac2e8736STakashi Iwai 			    struct hda_codec *codec,
4039ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
4040ac2e8736STakashi Iwai {
4041ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
4042ac2e8736STakashi Iwai 	return 0;
4043ac2e8736STakashi Iwai }
4044ac2e8736STakashi Iwai 
4045ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4046ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4047ac2e8736STakashi Iwai 			       unsigned int stream_tag,
4048ac2e8736STakashi Iwai 			       unsigned int format,
4049ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4050ac2e8736STakashi Iwai {
4051ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4052ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4053ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
4054ac2e8736STakashi Iwai 	return 0;
4055ac2e8736STakashi Iwai }
4056ac2e8736STakashi Iwai 
4057ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4058ac2e8736STakashi Iwai 			       struct hda_codec *codec,
4059ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
4060ac2e8736STakashi Iwai {
4061ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4062ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4063ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
4064ac2e8736STakashi Iwai 	return 0;
4065ac2e8736STakashi Iwai }
4066ac2e8736STakashi Iwai 
4067ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
4068ac2e8736STakashi Iwai 			     struct hda_codec *codec,
4069ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
4070ac2e8736STakashi Iwai {
4071ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
4072ac2e8736STakashi Iwai 	return 0;
4073ac2e8736STakashi Iwai }
4074ac2e8736STakashi Iwai 
407538cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
407638cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
407738cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
407838cf6f1aSTakashi Iwai {
407938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
408038cf6f1aSTakashi Iwai 	int err = 0;
408138cf6f1aSTakashi Iwai 
408238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
408338cf6f1aSTakashi Iwai 	if (!spec->indep_hp_enabled)
408438cf6f1aSTakashi Iwai 		err = -EBUSY;
408538cf6f1aSTakashi Iwai 	else
408638cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
4087e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4088e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
408938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
409038cf6f1aSTakashi Iwai 	return err;
409138cf6f1aSTakashi Iwai }
409238cf6f1aSTakashi Iwai 
409338cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
409438cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
409538cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
409638cf6f1aSTakashi Iwai {
409738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
409838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
409938cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
4100e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4101e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
410238cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
410338cf6f1aSTakashi Iwai 	return 0;
410438cf6f1aSTakashi Iwai }
410538cf6f1aSTakashi Iwai 
4106e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4107e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4108e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
4109e6b85f3cSTakashi Iwai 				    unsigned int format,
4110e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4111e6b85f3cSTakashi Iwai {
4112e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
4113e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4114e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
4115e6b85f3cSTakashi Iwai 	return 0;
4116e6b85f3cSTakashi Iwai }
4117e6b85f3cSTakashi Iwai 
4118e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4119e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
4120e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
4121e6b85f3cSTakashi Iwai {
4122e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
4123e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
4124e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
4125e6b85f3cSTakashi Iwai 	return 0;
4126e6b85f3cSTakashi Iwai }
4127e6b85f3cSTakashi Iwai 
4128352f7f91STakashi Iwai /*
4129352f7f91STakashi Iwai  * Digital out
4130352f7f91STakashi Iwai  */
4131352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
4132352f7f91STakashi Iwai 				 struct hda_codec *codec,
4133352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
4134352f7f91STakashi Iwai {
4135352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4136352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
4137352f7f91STakashi Iwai }
4138352f7f91STakashi Iwai 
4139352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
4140352f7f91STakashi Iwai 				    struct hda_codec *codec,
4141352f7f91STakashi Iwai 				    unsigned int stream_tag,
4142352f7f91STakashi Iwai 				    unsigned int format,
4143352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4144352f7f91STakashi Iwai {
4145352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4146352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
4147352f7f91STakashi Iwai 					     stream_tag, format, substream);
4148352f7f91STakashi Iwai }
4149352f7f91STakashi Iwai 
4150352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
4151352f7f91STakashi Iwai 				    struct hda_codec *codec,
4152352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
4153352f7f91STakashi Iwai {
4154352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4155352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
4156352f7f91STakashi Iwai }
4157352f7f91STakashi Iwai 
4158352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
4159352f7f91STakashi Iwai 				  struct hda_codec *codec,
4160352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
4161352f7f91STakashi Iwai {
4162352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4163352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
4164352f7f91STakashi Iwai }
4165352f7f91STakashi Iwai 
4166352f7f91STakashi Iwai /*
4167352f7f91STakashi Iwai  * Analog capture
4168352f7f91STakashi Iwai  */
4169ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
4170ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
4171ac2e8736STakashi Iwai 
4172352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4173352f7f91STakashi Iwai 				   struct hda_codec *codec,
4174352f7f91STakashi Iwai 				   unsigned int stream_tag,
4175352f7f91STakashi Iwai 				   unsigned int format,
4176352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
4177352f7f91STakashi Iwai {
4178352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4179352f7f91STakashi Iwai 
4180352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
418197ec558aSTakashi Iwai 				   stream_tag, 0, format);
4182ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4183ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
418497ec558aSTakashi Iwai 	return 0;
418597ec558aSTakashi Iwai }
418697ec558aSTakashi Iwai 
4187352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
418897ec558aSTakashi Iwai 				   struct hda_codec *codec,
418997ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
419097ec558aSTakashi Iwai {
4191352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
419297ec558aSTakashi Iwai 
4193352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
4194352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
4195ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
4196ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
419797ec558aSTakashi Iwai 	return 0;
419897ec558aSTakashi Iwai }
419997ec558aSTakashi Iwai 
4200352f7f91STakashi Iwai /*
4201352f7f91STakashi Iwai  */
4202352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
4203352f7f91STakashi Iwai 	.substreams = 1,
4204352f7f91STakashi Iwai 	.channels_min = 2,
4205352f7f91STakashi Iwai 	.channels_max = 8,
4206352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4207352f7f91STakashi Iwai 	.ops = {
4208352f7f91STakashi Iwai 		.open = playback_pcm_open,
420938cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
4210352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
4211352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
4212352f7f91STakashi Iwai 	},
4213352f7f91STakashi Iwai };
4214352f7f91STakashi Iwai 
4215352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
4216352f7f91STakashi Iwai 	.substreams = 1,
4217352f7f91STakashi Iwai 	.channels_min = 2,
4218352f7f91STakashi Iwai 	.channels_max = 2,
4219352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4220ac2e8736STakashi Iwai 	.ops = {
4221ac2e8736STakashi Iwai 		.open = capture_pcm_open,
4222ac2e8736STakashi Iwai 		.close = capture_pcm_close,
4223ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
4224ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
4225ac2e8736STakashi Iwai 	},
4226352f7f91STakashi Iwai };
4227352f7f91STakashi Iwai 
4228352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
4229352f7f91STakashi Iwai 	.substreams = 1,
4230352f7f91STakashi Iwai 	.channels_min = 2,
4231352f7f91STakashi Iwai 	.channels_max = 2,
4232352f7f91STakashi Iwai 	/* NID is set in build_pcms */
423338cf6f1aSTakashi Iwai 	.ops = {
423438cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
4235e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
4236e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
4237e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
423838cf6f1aSTakashi Iwai 	},
4239352f7f91STakashi Iwai };
4240352f7f91STakashi Iwai 
4241352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
4242352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
4243352f7f91STakashi Iwai 	.channels_min = 2,
4244352f7f91STakashi Iwai 	.channels_max = 2,
4245352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4246352f7f91STakashi Iwai 	.ops = {
4247ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
4248ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
4249352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
4250352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
4251352f7f91STakashi Iwai 	},
4252352f7f91STakashi Iwai };
4253352f7f91STakashi Iwai 
4254352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
4255352f7f91STakashi Iwai 	.substreams = 1,
4256352f7f91STakashi Iwai 	.channels_min = 2,
4257352f7f91STakashi Iwai 	.channels_max = 2,
4258352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4259352f7f91STakashi Iwai 	.ops = {
4260352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
4261352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
4262352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
4263352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
4264352f7f91STakashi Iwai 	},
4265352f7f91STakashi Iwai };
4266352f7f91STakashi Iwai 
4267352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
4268352f7f91STakashi Iwai 	.substreams = 1,
4269352f7f91STakashi Iwai 	.channels_min = 2,
4270352f7f91STakashi Iwai 	.channels_max = 2,
4271352f7f91STakashi Iwai 	/* NID is set in build_pcms */
4272352f7f91STakashi Iwai };
4273352f7f91STakashi Iwai 
4274352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
4275352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
4276352f7f91STakashi Iwai 	.substreams = 0,
4277352f7f91STakashi Iwai 	.channels_min = 0,
4278352f7f91STakashi Iwai 	.channels_max = 0,
4279352f7f91STakashi Iwai };
4280352f7f91STakashi Iwai 
4281352f7f91STakashi Iwai /*
4282352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
4283352f7f91STakashi Iwai  */
4284352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
42851da177e4SLinus Torvalds {
4286352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4287352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
42881da177e4SLinus Torvalds 
4289352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
4290352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
4291352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
4292352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
4293352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
4294352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
4295352f7f91STakashi Iwai 					   spec->cur_adc_format);
4296352f7f91STakashi Iwai 		return true;
4297352f7f91STakashi Iwai 	}
4298352f7f91STakashi Iwai 	return false;
4299352f7f91STakashi Iwai }
4300352f7f91STakashi Iwai 
4301352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
4302352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
4303352f7f91STakashi Iwai 				       struct hda_codec *codec,
4304352f7f91STakashi Iwai 				       unsigned int stream_tag,
4305352f7f91STakashi Iwai 				       unsigned int format,
4306352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4307352f7f91STakashi Iwai {
4308352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4309352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
4310352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
4311352f7f91STakashi Iwai 	spec->cur_adc_format = format;
4312352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
43131da177e4SLinus Torvalds 	return 0;
43141da177e4SLinus Torvalds }
43151da177e4SLinus Torvalds 
4316352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
4317352f7f91STakashi Iwai 				       struct hda_codec *codec,
4318352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
4319352f7f91STakashi Iwai {
4320352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4321352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
4322352f7f91STakashi Iwai 	spec->cur_adc = 0;
4323352f7f91STakashi Iwai 	return 0;
4324352f7f91STakashi Iwai }
4325352f7f91STakashi Iwai 
4326352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
4327352f7f91STakashi Iwai 	.substreams = 1,
4328352f7f91STakashi Iwai 	.channels_min = 2,
4329352f7f91STakashi Iwai 	.channels_max = 2,
4330352f7f91STakashi Iwai 	.nid = 0, /* fill later */
4331352f7f91STakashi Iwai 	.ops = {
4332352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
4333352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
4334352f7f91STakashi Iwai 	},
4335352f7f91STakashi Iwai };
4336352f7f91STakashi Iwai 
4337f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
4338f873e536STakashi Iwai 				 const char *chip_name)
4339f873e536STakashi Iwai {
4340f873e536STakashi Iwai 	char *p;
4341f873e536STakashi Iwai 
4342f873e536STakashi Iwai 	if (*str)
4343f873e536STakashi Iwai 		return;
4344f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
4345f873e536STakashi Iwai 
4346f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
4347f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
4348f873e536STakashi Iwai 		if (!isalnum(p[1])) {
4349f873e536STakashi Iwai 			*p = 0;
4350f873e536STakashi Iwai 			break;
4351f873e536STakashi Iwai 		}
4352f873e536STakashi Iwai 	}
4353f873e536STakashi Iwai 	strlcat(str, sfx, len);
4354f873e536STakashi Iwai }
4355f873e536STakashi Iwai 
4356352f7f91STakashi Iwai /* build PCM streams based on the parsed results */
4357352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
4358352f7f91STakashi Iwai {
4359352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4360352f7f91STakashi Iwai 	struct hda_pcm *info = spec->pcm_rec;
4361352f7f91STakashi Iwai 	const struct hda_pcm_stream *p;
4362352f7f91STakashi Iwai 	bool have_multi_adcs;
4363352f7f91STakashi Iwai 
43641da177e4SLinus Torvalds 	codec->num_pcms = 1;
43651da177e4SLinus Torvalds 	codec->pcm_info = info;
43661da177e4SLinus Torvalds 
4367352f7f91STakashi Iwai 	if (spec->no_analog)
4368352f7f91STakashi Iwai 		goto skip_analog;
4369352f7f91STakashi Iwai 
4370f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
4371f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
4372f873e536STakashi Iwai 			     " Analog", codec->chip_name);
4373352f7f91STakashi Iwai 	info->name = spec->stream_name_analog;
4374352f7f91STakashi Iwai 
4375352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
4376352f7f91STakashi Iwai 		p = spec->stream_analog_playback;
4377352f7f91STakashi Iwai 		if (!p)
4378352f7f91STakashi Iwai 			p = &pcm_analog_playback;
4379352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4380352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
4381352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
4382352f7f91STakashi Iwai 			spec->multiout.max_channels;
4383352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
4384352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
4385352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
4386352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
4387352f7f91STakashi Iwai 	}
4388352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
4389352f7f91STakashi Iwai 		p = spec->stream_analog_capture;
4390352f7f91STakashi Iwai 		if (!p) {
4391352f7f91STakashi Iwai 			if (spec->dyn_adc_switch)
4392352f7f91STakashi Iwai 				p = &dyn_adc_pcm_analog_capture;
4393352f7f91STakashi Iwai 			else
4394352f7f91STakashi Iwai 				p = &pcm_analog_capture;
4395352f7f91STakashi Iwai 		}
4396352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4397352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
4398352f7f91STakashi Iwai 	}
4399352f7f91STakashi Iwai 
4400352f7f91STakashi Iwai  skip_analog:
4401352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
4402352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
4403f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
4404352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
4405f873e536STakashi Iwai 				     " Digital", codec->chip_name);
4406352f7f91STakashi Iwai 		codec->num_pcms = 2;
4407352f7f91STakashi Iwai 		codec->slave_dig_outs = spec->multiout.slave_dig_outs;
4408352f7f91STakashi Iwai 		info = spec->pcm_rec + 1;
4409352f7f91STakashi Iwai 		info->name = spec->stream_name_digital;
4410352f7f91STakashi Iwai 		if (spec->dig_out_type)
4411352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
4412352f7f91STakashi Iwai 		else
4413352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
4414352f7f91STakashi Iwai 		if (spec->multiout.dig_out_nid) {
4415352f7f91STakashi Iwai 			p = spec->stream_digital_playback;
4416352f7f91STakashi Iwai 			if (!p)
4417352f7f91STakashi Iwai 				p = &pcm_digital_playback;
4418352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4419352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
4420352f7f91STakashi Iwai 		}
4421352f7f91STakashi Iwai 		if (spec->dig_in_nid) {
4422352f7f91STakashi Iwai 			p = spec->stream_digital_capture;
4423352f7f91STakashi Iwai 			if (!p)
4424352f7f91STakashi Iwai 				p = &pcm_digital_capture;
4425352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4426352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
4427352f7f91STakashi Iwai 		}
4428352f7f91STakashi Iwai 	}
4429352f7f91STakashi Iwai 
4430352f7f91STakashi Iwai 	if (spec->no_analog)
4431352f7f91STakashi Iwai 		return 0;
4432352f7f91STakashi Iwai 
4433352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
4434352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
4435352f7f91STakashi Iwai 	 */
4436352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
4437352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
4438352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
4439352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
4440352f7f91STakashi Iwai 		codec->num_pcms = 3;
4441352f7f91STakashi Iwai 		info = spec->pcm_rec + 2;
4442352f7f91STakashi Iwai 		info->name = spec->stream_name_analog;
4443352f7f91STakashi Iwai 		if (spec->alt_dac_nid) {
4444352f7f91STakashi Iwai 			p = spec->stream_analog_alt_playback;
4445352f7f91STakashi Iwai 			if (!p)
4446352f7f91STakashi Iwai 				p = &pcm_analog_alt_playback;
4447352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p;
4448352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
4449352f7f91STakashi Iwai 				spec->alt_dac_nid;
4450352f7f91STakashi Iwai 		} else {
4451352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
4452352f7f91STakashi Iwai 				pcm_null_stream;
4453352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
4454352f7f91STakashi Iwai 		}
4455352f7f91STakashi Iwai 		if (have_multi_adcs) {
4456352f7f91STakashi Iwai 			p = spec->stream_analog_alt_capture;
4457352f7f91STakashi Iwai 			if (!p)
4458352f7f91STakashi Iwai 				p = &pcm_analog_alt_capture;
4459352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *p;
4460352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
4461352f7f91STakashi Iwai 				spec->adc_nids[1];
4462352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
4463352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
4464352f7f91STakashi Iwai 		} else {
4465352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
4466352f7f91STakashi Iwai 				pcm_null_stream;
4467352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = 0;
4468352f7f91STakashi Iwai 		}
44691da177e4SLinus Torvalds 	}
44701da177e4SLinus Torvalds 
44711da177e4SLinus Torvalds 	return 0;
44721da177e4SLinus Torvalds }
4473352f7f91STakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
4474352f7f91STakashi Iwai 
4475352f7f91STakashi Iwai 
4476352f7f91STakashi Iwai /*
4477352f7f91STakashi Iwai  * Standard auto-parser initializations
4478352f7f91STakashi Iwai  */
4479352f7f91STakashi Iwai 
4480d4156930STakashi Iwai /* configure the given path as a proper output */
44812c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
4482352f7f91STakashi Iwai {
4483352f7f91STakashi Iwai 	struct nid_path *path;
4484d4156930STakashi Iwai 	hda_nid_t pin;
4485352f7f91STakashi Iwai 
4486196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
4487d4156930STakashi Iwai 	if (!path || !path->depth)
4488352f7f91STakashi Iwai 		return;
4489d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
44902c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
4491e1284af7STakashi Iwai 	snd_hda_activate_path(codec, path, path->active, true);
4492e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
4493352f7f91STakashi Iwai }
4494352f7f91STakashi Iwai 
4495352f7f91STakashi Iwai /* initialize primary output paths */
4496352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
4497352f7f91STakashi Iwai {
4498352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4499352f7f91STakashi Iwai 	int i;
4500352f7f91STakashi Iwai 
4501d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
45022c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
4503352f7f91STakashi Iwai }
4504352f7f91STakashi Iwai 
4505db23fd19STakashi Iwai 
45062c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
4507352f7f91STakashi Iwai {
4508352f7f91STakashi Iwai 	int i;
4509352f7f91STakashi Iwai 
4510d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
45112c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
4512352f7f91STakashi Iwai }
4513db23fd19STakashi Iwai 
4514db23fd19STakashi Iwai /* initialize hp and speaker paths */
4515db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
4516db23fd19STakashi Iwai {
4517db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4518db23fd19STakashi Iwai 
4519db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
45202c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
4521db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
4522db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
45232c12c30dSTakashi Iwai 				 spec->speaker_paths);
4524352f7f91STakashi Iwai }
4525352f7f91STakashi Iwai 
4526352f7f91STakashi Iwai /* initialize multi-io paths */
4527352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
4528352f7f91STakashi Iwai {
4529352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4530352f7f91STakashi Iwai 	int i;
4531352f7f91STakashi Iwai 
4532352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
4533352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
4534352f7f91STakashi Iwai 		struct nid_path *path;
4535196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
4536352f7f91STakashi Iwai 		if (!path)
4537352f7f91STakashi Iwai 			continue;
4538352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
4539352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
45402c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
4541352f7f91STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, true);
4542352f7f91STakashi Iwai 	}
4543352f7f91STakashi Iwai }
4544352f7f91STakashi Iwai 
4545352f7f91STakashi Iwai /* set up input pins and loopback paths */
4546352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
4547352f7f91STakashi Iwai {
4548352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4549352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4550352f7f91STakashi Iwai 	int i;
4551352f7f91STakashi Iwai 
4552352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4553352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4554352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
45552c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
4556352f7f91STakashi Iwai 
4557352f7f91STakashi Iwai 		/* init loopback inputs */
4558352f7f91STakashi Iwai 		if (spec->mixer_nid) {
4559352f7f91STakashi Iwai 			struct nid_path *path;
4560196c1766STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, spec->loopback_paths[i]);
4561352f7f91STakashi Iwai 			if (path)
4562352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path,
4563352f7f91STakashi Iwai 						      path->active, false);
4564352f7f91STakashi Iwai 		}
4565352f7f91STakashi Iwai 	}
4566352f7f91STakashi Iwai }
4567352f7f91STakashi Iwai 
4568352f7f91STakashi Iwai /* initialize ADC paths */
4569352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
4570352f7f91STakashi Iwai {
4571352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4572352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
4573352f7f91STakashi Iwai 	struct nid_path *path;
4574352f7f91STakashi Iwai 	int i, c, nums;
4575352f7f91STakashi Iwai 
4576352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4577352f7f91STakashi Iwai 		nums = 1;
4578352f7f91STakashi Iwai 	else
4579352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
4580352f7f91STakashi Iwai 
4581352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
4582352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
4583c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
4584352f7f91STakashi Iwai 			if (path) {
4585352f7f91STakashi Iwai 				bool active = path->active;
4586352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
4587352f7f91STakashi Iwai 					active = true;
4588352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
4589352f7f91STakashi Iwai 			}
4590352f7f91STakashi Iwai 		}
4591352f7f91STakashi Iwai 	}
4592352f7f91STakashi Iwai 
4593352f7f91STakashi Iwai 	if (spec->shared_mic_hp)
4594352f7f91STakashi Iwai 		update_shared_mic_hp(codec, spec->cur_mux[0]);
4595352f7f91STakashi Iwai 
4596352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
4597a90229e0STakashi Iwai 		spec->cap_sync_hook(codec, NULL);
4598352f7f91STakashi Iwai }
4599352f7f91STakashi Iwai 
4600352f7f91STakashi Iwai /* set right pin controls for digital I/O */
4601352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
4602352f7f91STakashi Iwai {
4603352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4604352f7f91STakashi Iwai 	int i;
4605352f7f91STakashi Iwai 	hda_nid_t pin;
4606352f7f91STakashi Iwai 
4607d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
46082c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
4609352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
46102430d7b7STakashi Iwai 	if (pin) {
46112430d7b7STakashi Iwai 		struct nid_path *path;
46122c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
46132430d7b7STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->digin_path);
46142430d7b7STakashi Iwai 		if (path)
46152430d7b7STakashi Iwai 			snd_hda_activate_path(codec, path, path->active, false);
46162430d7b7STakashi Iwai 	}
4617352f7f91STakashi Iwai }
4618352f7f91STakashi Iwai 
4619973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
4620973e4972STakashi Iwai  * invalid unsol tags by some reason
4621973e4972STakashi Iwai  */
4622973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
4623973e4972STakashi Iwai {
4624973e4972STakashi Iwai 	int i;
4625973e4972STakashi Iwai 
4626973e4972STakashi Iwai 	for (i = 0; i < codec->init_pins.used; i++) {
4627973e4972STakashi Iwai 		struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
4628973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
4629973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
4630973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
4631973e4972STakashi Iwai 			snd_hda_codec_update_cache(codec, nid, 0,
4632973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
4633973e4972STakashi Iwai 	}
4634973e4972STakashi Iwai }
4635973e4972STakashi Iwai 
46365187ac16STakashi Iwai /*
46375187ac16STakashi Iwai  * initialize the generic spec;
46385187ac16STakashi Iwai  * this can be put as patch_ops.init function
46395187ac16STakashi Iwai  */
4640352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
4641352f7f91STakashi Iwai {
4642352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4643352f7f91STakashi Iwai 
4644352f7f91STakashi Iwai 	if (spec->init_hook)
4645352f7f91STakashi Iwai 		spec->init_hook(codec);
4646352f7f91STakashi Iwai 
4647352f7f91STakashi Iwai 	snd_hda_apply_verbs(codec);
4648352f7f91STakashi Iwai 
46493bbcd274STakashi Iwai 	codec->cached_write = 1;
46503bbcd274STakashi Iwai 
4651352f7f91STakashi Iwai 	init_multi_out(codec);
4652352f7f91STakashi Iwai 	init_extra_out(codec);
4653352f7f91STakashi Iwai 	init_multi_io(codec);
4654352f7f91STakashi Iwai 	init_analog_input(codec);
4655352f7f91STakashi Iwai 	init_input_src(codec);
4656352f7f91STakashi Iwai 	init_digital(codec);
4657352f7f91STakashi Iwai 
4658973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
4659973e4972STakashi Iwai 
4660352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
4661a5cc2509STakashi Iwai 	update_automute_all(codec);
4662352f7f91STakashi Iwai 
46633bbcd274STakashi Iwai 	snd_hda_codec_flush_amp_cache(codec);
46643bbcd274STakashi Iwai 	snd_hda_codec_flush_cmd_cache(codec);
46653bbcd274STakashi Iwai 
4666352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
4667352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
4668352f7f91STakashi Iwai 
4669352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
4670352f7f91STakashi Iwai 	return 0;
4671352f7f91STakashi Iwai }
4672fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_init);
4673fce52a3bSTakashi Iwai 
46745187ac16STakashi Iwai /*
46755187ac16STakashi Iwai  * free the generic spec;
46765187ac16STakashi Iwai  * this can be put as patch_ops.free function
46775187ac16STakashi Iwai  */
4678fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
4679fce52a3bSTakashi Iwai {
4680fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
4681fce52a3bSTakashi Iwai 	kfree(codec->spec);
4682fce52a3bSTakashi Iwai 	codec->spec = NULL;
4683fce52a3bSTakashi Iwai }
4684fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_free);
4685fce52a3bSTakashi Iwai 
4686fce52a3bSTakashi Iwai #ifdef CONFIG_PM
46875187ac16STakashi Iwai /*
46885187ac16STakashi Iwai  * check the loopback power save state;
46895187ac16STakashi Iwai  * this can be put as patch_ops.check_power_status function
46905187ac16STakashi Iwai  */
4691fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
4692fce52a3bSTakashi Iwai {
4693fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4694fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
4695fce52a3bSTakashi Iwai }
4696fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_gen_check_power_status);
4697fce52a3bSTakashi Iwai #endif
4698352f7f91STakashi Iwai 
4699352f7f91STakashi Iwai 
4700352f7f91STakashi Iwai /*
4701352f7f91STakashi Iwai  * the generic codec support
4702352f7f91STakashi Iwai  */
47031da177e4SLinus Torvalds 
4704352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
4705352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
4706352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
4707352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
4708fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
4709352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
471083012a7cSTakashi Iwai #ifdef CONFIG_PM
4711fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
4712cb53c626STakashi Iwai #endif
47131da177e4SLinus Torvalds };
47141da177e4SLinus Torvalds 
47151da177e4SLinus Torvalds int snd_hda_parse_generic_codec(struct hda_codec *codec)
47161da177e4SLinus Torvalds {
4717352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
47181da177e4SLinus Torvalds 	int err;
47191da177e4SLinus Torvalds 
4720e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
4721352f7f91STakashi Iwai 	if (!spec)
47221da177e4SLinus Torvalds 		return -ENOMEM;
4723352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
47241da177e4SLinus Torvalds 	codec->spec = spec;
47251da177e4SLinus Torvalds 
47269eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
47279eb413e5STakashi Iwai 	if (err < 0)
47289eb413e5STakashi Iwai 		return err;
47299eb413e5STakashi Iwai 
47309eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
4731352f7f91STakashi Iwai 	if (err < 0)
47321da177e4SLinus Torvalds 		goto error;
47331da177e4SLinus Torvalds 
47341da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
47351da177e4SLinus Torvalds 	return 0;
47361da177e4SLinus Torvalds 
47371da177e4SLinus Torvalds error:
4738fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
47391da177e4SLinus Torvalds 	return err;
47401da177e4SLinus Torvalds }
4741fce52a3bSTakashi Iwai EXPORT_SYMBOL_HDA(snd_hda_parse_generic_codec);
4742