xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision e65bf997)
1d0fa1179SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  * Universal Interface for Intel High Definition Audio Codec
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Generic widget tree parser
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
81da177e4SLinus Torvalds  */
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds #include <linux/init.h>
111da177e4SLinus Torvalds #include <linux/slab.h>
12d81a6d71SPaul Gortmaker #include <linux/export.h>
13352f7f91STakashi Iwai #include <linux/sort.h>
1455196fffSTakashi Iwai #include <linux/delay.h>
15f873e536STakashi Iwai #include <linux/ctype.h>
16f873e536STakashi Iwai #include <linux/string.h>
1729476558STakashi Iwai #include <linux/bitops.h>
18b21bdd0dSTakashi Iwai #include <linux/module.h>
19b3802783STakashi Iwai #include <linux/leds.h>
201da177e4SLinus Torvalds #include <sound/core.h>
21352f7f91STakashi Iwai #include <sound/jack.h>
22d89c6c0cSTakashi Iwai #include <sound/tlv.h>
23be57bfffSPierre-Louis Bossart #include <sound/hda_codec.h>
241da177e4SLinus Torvalds #include "hda_local.h"
25352f7f91STakashi Iwai #include "hda_auto_parser.h"
26352f7f91STakashi Iwai #include "hda_jack.h"
277504b6cdSTakashi Iwai #include "hda_beep.h"
28352f7f91STakashi Iwai #include "hda_generic.h"
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds 
31dda42bd0STakashi Iwai /**
32dda42bd0STakashi Iwai  * snd_hda_gen_spec_init - initialize hda_gen_spec struct
33dda42bd0STakashi Iwai  * @spec: hda_gen_spec object to initialize
34dda42bd0STakashi Iwai  *
35dda42bd0STakashi Iwai  * Initialize the given hda_gen_spec object.
36dda42bd0STakashi Iwai  */
37352f7f91STakashi Iwai int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
381da177e4SLinus Torvalds {
39352f7f91STakashi Iwai 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
40352f7f91STakashi Iwai 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
410186f4f4STakashi Iwai 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
4238cf6f1aSTakashi Iwai 	mutex_init(&spec->pcm_mutex);
43352f7f91STakashi Iwai 	return 0;
44352f7f91STakashi Iwai }
452698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
461da177e4SLinus Torvalds 
47dda42bd0STakashi Iwai /**
48dda42bd0STakashi Iwai  * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
49dda42bd0STakashi Iwai  * @spec: hda_gen_spec object
50dda42bd0STakashi Iwai  * @name: name string to override the template, NULL if unchanged
51dda42bd0STakashi Iwai  * @temp: template for the new kctl
52dda42bd0STakashi Iwai  *
53dda42bd0STakashi Iwai  * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
54dda42bd0STakashi Iwai  * element based on the given snd_kcontrol_new template @temp and the
55dda42bd0STakashi Iwai  * name string @name to the list in @spec.
56dda42bd0STakashi Iwai  * Returns the newly created object or NULL as error.
57dda42bd0STakashi Iwai  */
5812c93df6STakashi Iwai struct snd_kcontrol_new *
5912c93df6STakashi Iwai snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
60352f7f91STakashi Iwai 		     const struct snd_kcontrol_new *temp)
61352f7f91STakashi Iwai {
62352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
63352f7f91STakashi Iwai 	if (!knew)
64352f7f91STakashi Iwai 		return NULL;
65352f7f91STakashi Iwai 	*knew = *temp;
66352f7f91STakashi Iwai 	if (name)
67352f7f91STakashi Iwai 		knew->name = kstrdup(name, GFP_KERNEL);
68352f7f91STakashi Iwai 	else if (knew->name)
69352f7f91STakashi Iwai 		knew->name = kstrdup(knew->name, GFP_KERNEL);
70352f7f91STakashi Iwai 	if (!knew->name)
71352f7f91STakashi Iwai 		return NULL;
72352f7f91STakashi Iwai 	return knew;
73352f7f91STakashi Iwai }
742698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
75352f7f91STakashi Iwai 
76352f7f91STakashi Iwai static void free_kctls(struct hda_gen_spec *spec)
77352f7f91STakashi Iwai {
78352f7f91STakashi Iwai 	if (spec->kctls.list) {
79352f7f91STakashi Iwai 		struct snd_kcontrol_new *kctl = spec->kctls.list;
80352f7f91STakashi Iwai 		int i;
81352f7f91STakashi Iwai 		for (i = 0; i < spec->kctls.used; i++)
82352f7f91STakashi Iwai 			kfree(kctl[i].name);
83352f7f91STakashi Iwai 	}
84352f7f91STakashi Iwai 	snd_array_free(&spec->kctls);
85352f7f91STakashi Iwai }
86352f7f91STakashi Iwai 
87a8dca460STakashi Iwai static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
88352f7f91STakashi Iwai {
891da177e4SLinus Torvalds 	if (!spec)
901da177e4SLinus Torvalds 		return;
91352f7f91STakashi Iwai 	free_kctls(spec);
92352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
930186f4f4STakashi Iwai 	snd_array_free(&spec->loopback_list);
941da177e4SLinus Torvalds }
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds /*
971c70a583STakashi Iwai  * store user hints
981c70a583STakashi Iwai  */
991c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
1001c70a583STakashi Iwai {
1011c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1021c70a583STakashi Iwai 	int val;
1031c70a583STakashi Iwai 
1041c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1051c70a583STakashi Iwai 	if (val >= 0)
1061c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1071c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1081c70a583STakashi Iwai 	if (val >= 0)
1091c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1101c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1111c70a583STakashi Iwai 	if (val >= 0)
1121c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1131c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1141c70a583STakashi Iwai 	if (val >= 0)
1151c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1221c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1231c70a583STakashi Iwai 	if (val >= 0)
1241c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1251c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1261c70a583STakashi Iwai 	if (val >= 0)
1271c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1281c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1291c70a583STakashi Iwai 	if (val >= 0)
1301c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
131967b1307STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_save_node");
132e6feb5d0STakashi Iwai 	if (val >= 0)
133967b1307STakashi Iwai 		codec->power_save_node = !!val;
1341c70a583STakashi Iwai 
135f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
136f72706beSTakashi Iwai 	if (val >= 0)
137f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1381c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1391c70a583STakashi Iwai 	if (val >= 0)
1401c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1411c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1421c70a583STakashi Iwai 	if (val >= 0)
1431c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1447eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1457eebffd3STakashi Iwai 	if (val >= 0)
1467eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1471c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1481c70a583STakashi Iwai 	if (val >= 0)
1491c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1501c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1511c70a583STakashi Iwai 	if (val >= 0)
1521c70a583STakashi Iwai 		spec->no_primary_hp = !val;
153da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
154da96fb5bSTakashi Iwai 	if (val >= 0)
155da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1561c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1571c70a583STakashi Iwai 	if (val >= 0)
1581c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1591c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1601c70a583STakashi Iwai 	if (val >= 0)
1611c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1621c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1631c70a583STakashi Iwai 	if (val >= 0)
1641c70a583STakashi Iwai 		spec->indep_hp = !!val;
1651c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1661c70a583STakashi Iwai 	if (val >= 0)
1671c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
168f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1691c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1701c70a583STakashi Iwai 	if (val >= 0)
171f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
17229476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
17329476558STakashi Iwai 	if (val >= 0)
174f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
175f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
176f811c3cfSTakashi Iwai 	if (val >= 0)
177f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
17855196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
17955196fffSTakashi Iwai 	if (val >= 0)
18055196fffSTakashi Iwai 		spec->power_down_unused = !!val;
181967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
182967303daSTakashi Iwai 	if (val >= 0)
183967303daSTakashi Iwai 		spec->hp_mic = !!val;
184967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
185967303daSTakashi Iwai 	if (val >= 0)
186967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1877480316cSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "vmaster");
1887480316cSTakashi Iwai 	if (val >= 0)
1897480316cSTakashi Iwai 		spec->suppress_vmaster = !val;
1901c70a583STakashi Iwai 
1911c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1921c70a583STakashi Iwai 		spec->mixer_nid = val;
1931c70a583STakashi Iwai }
1941c70a583STakashi Iwai 
1951c70a583STakashi Iwai /*
1962c12c30dSTakashi Iwai  * pin control value accesses
1972c12c30dSTakashi Iwai  */
1982c12c30dSTakashi Iwai 
1992c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
200401caff7STakashi Iwai 	snd_hda_codec_write_cache(codec, pin, 0, \
2012c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
2022c12c30dSTakashi Iwai 
2032c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
2042c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
2052c12c30dSTakashi Iwai {
2062c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
2072c12c30dSTakashi Iwai }
2082c12c30dSTakashi Iwai 
2092c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2102c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2112c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2122c12c30dSTakashi Iwai {
2132c12c30dSTakashi Iwai 	if (!pin)
2142c12c30dSTakashi Iwai 		return;
2152c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2162c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2172c12c30dSTakashi Iwai 	if (do_write)
2182c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2192c12c30dSTakashi Iwai }
2202c12c30dSTakashi Iwai 
2212c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2222c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2232c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2242c12c30dSTakashi Iwai {
2252c12c30dSTakashi Iwai 	int i;
2262c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2272c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2282c12c30dSTakashi Iwai }
2292c12c30dSTakashi Iwai 
2302c12c30dSTakashi Iwai /*
231352f7f91STakashi Iwai  * parsing paths
2321da177e4SLinus Torvalds  */
2331da177e4SLinus Torvalds 
2343ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2353ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2363ca529d3STakashi Iwai {
2373ca529d3STakashi Iwai 	int i;
2383ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2393ca529d3STakashi Iwai 		if (list[i] == nid)
2403ca529d3STakashi Iwai 			return i;
2413ca529d3STakashi Iwai 	return -1;
2423ca529d3STakashi Iwai }
2433ca529d3STakashi Iwai 
2443ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2453ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2463ca529d3STakashi Iwai {
2473ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2483ca529d3STakashi Iwai }
2493ca529d3STakashi Iwai 
250f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
251f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2523ca529d3STakashi Iwai 				     int anchor_nid)
2531da177e4SLinus Torvalds {
254352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
255a9c2dfc8STakashi Iwai 	struct nid_path *path;
256352f7f91STakashi Iwai 	int i;
2571da177e4SLinus Torvalds 
258a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
259352f7f91STakashi Iwai 		if (path->depth <= 0)
260352f7f91STakashi Iwai 			continue;
261352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
262f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2633ca529d3STakashi Iwai 			if (!anchor_nid ||
2643ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2653ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
266352f7f91STakashi Iwai 				return path;
2671da177e4SLinus Torvalds 		}
268f5172a7eSTakashi Iwai 	}
2691da177e4SLinus Torvalds 	return NULL;
2701da177e4SLinus Torvalds }
271f5172a7eSTakashi Iwai 
272dda42bd0STakashi Iwai /**
273dda42bd0STakashi Iwai  * snd_hda_get_path_idx - get the index number corresponding to the path
274dda42bd0STakashi Iwai  * instance
275dda42bd0STakashi Iwai  * @codec: the HDA codec
276dda42bd0STakashi Iwai  * @path: nid_path object
277dda42bd0STakashi Iwai  *
278dda42bd0STakashi Iwai  * The returned index starts from 1, i.e. the actual array index with offset 1,
279dda42bd0STakashi Iwai  * and zero is handled as an invalid path
280196c1766STakashi Iwai  */
281196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
282196c1766STakashi Iwai {
283196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
284196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
285196c1766STakashi Iwai 	ssize_t idx;
286196c1766STakashi Iwai 
287196c1766STakashi Iwai 	if (!spec->paths.used)
288196c1766STakashi Iwai 		return 0;
289196c1766STakashi Iwai 	idx = path - array;
290196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
291196c1766STakashi Iwai 		return 0;
292196c1766STakashi Iwai 	return idx + 1;
293196c1766STakashi Iwai }
2942698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
295196c1766STakashi Iwai 
296dda42bd0STakashi Iwai /**
297dda42bd0STakashi Iwai  * snd_hda_get_path_from_idx - get the path instance corresponding to the
298dda42bd0STakashi Iwai  * given index number
299dda42bd0STakashi Iwai  * @codec: the HDA codec
300dda42bd0STakashi Iwai  * @idx: the path index
301dda42bd0STakashi Iwai  */
302196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
303196c1766STakashi Iwai {
304196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
305196c1766STakashi Iwai 
306196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
307196c1766STakashi Iwai 		return NULL;
308196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
309196c1766STakashi Iwai }
3102698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
311196c1766STakashi Iwai 
312352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
313352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3141da177e4SLinus Torvalds {
315352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
316a9c2dfc8STakashi Iwai 	const struct nid_path *path;
317352f7f91STakashi Iwai 	int i;
318352f7f91STakashi Iwai 
319a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
320352f7f91STakashi Iwai 		if (path->path[0] == nid)
321352f7f91STakashi Iwai 			return true;
322352f7f91STakashi Iwai 	}
323352f7f91STakashi Iwai 	return false;
3241da177e4SLinus Torvalds }
3251da177e4SLinus Torvalds 
326352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
327352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
328352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3291da177e4SLinus Torvalds {
330352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
331352f7f91STakashi Iwai 		return false;
332352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3331da177e4SLinus Torvalds }
3341da177e4SLinus Torvalds 
335352f7f91STakashi Iwai /* nid, dir and idx */
336352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
337352f7f91STakashi Iwai 
338352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
339352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3401da177e4SLinus Torvalds {
341352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
342a9c2dfc8STakashi Iwai 	const struct nid_path *path;
343352f7f91STakashi Iwai 	int i;
344352f7f91STakashi Iwai 
345352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
346a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
347352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
348352f7f91STakashi Iwai 			return true;
349352f7f91STakashi Iwai 	}
350352f7f91STakashi Iwai 	return false;
3511da177e4SLinus Torvalds }
3521da177e4SLinus Torvalds 
353352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
354352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3558999bf0aSTakashi Iwai 			      int dir, int idx, int type)
356cb53c626STakashi Iwai {
357352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3588999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
359cb53c626STakashi Iwai }
360352f7f91STakashi Iwai 
3614e76a883STakashi Iwai static void print_nid_path(struct hda_codec *codec,
3624e76a883STakashi Iwai 			   const char *pfx, struct nid_path *path)
3630c8c0f56STakashi Iwai {
3640c8c0f56STakashi Iwai 	char buf[40];
365d82353e5SJoe Perches 	char *pos = buf;
3660c8c0f56STakashi Iwai 	int i;
3670c8c0f56STakashi Iwai 
368d82353e5SJoe Perches 	*pos = 0;
369d82353e5SJoe Perches 	for (i = 0; i < path->depth; i++)
370d82353e5SJoe Perches 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
371d82353e5SJoe Perches 				 pos != buf ? ":" : "",
372d82353e5SJoe Perches 				 path->path[i]);
3730c8c0f56STakashi Iwai 
374d82353e5SJoe Perches 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
3750c8c0f56STakashi Iwai }
3760c8c0f56STakashi Iwai 
377352f7f91STakashi Iwai /* called recursively */
378352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
379352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3803ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3813ca529d3STakashi Iwai 			     int depth)
382352f7f91STakashi Iwai {
383ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
384352f7f91STakashi Iwai 	int i, nums;
385352f7f91STakashi Iwai 
3863ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3873ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3883ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3893ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
390352f7f91STakashi Iwai 
391ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
392352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
393352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
394352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
395352f7f91STakashi Iwai 			 * try to find an empty DAC
396352f7f91STakashi Iwai 			 */
397352f7f91STakashi Iwai 			if (from_nid ||
398352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
399352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
400352f7f91STakashi Iwai 				continue;
401352f7f91STakashi Iwai 		}
4023ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
4033ca529d3STakashi Iwai 		if (anchor_nid <= 0)
404352f7f91STakashi Iwai 			goto found;
405352f7f91STakashi Iwai 	}
406352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
407352f7f91STakashi Iwai 		return false;
408352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
409352f7f91STakashi Iwai 		unsigned int type;
410352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
411352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
412352f7f91STakashi Iwai 		    type == AC_WID_PIN)
413352f7f91STakashi Iwai 			continue;
414352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4153ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
416352f7f91STakashi Iwai 			goto found;
417352f7f91STakashi Iwai 	}
418352f7f91STakashi Iwai 	return false;
419352f7f91STakashi Iwai 
420352f7f91STakashi Iwai  found:
421352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
422352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
423352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
424352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
425352f7f91STakashi Iwai 	path->depth++;
426352f7f91STakashi Iwai 	return true;
427352f7f91STakashi Iwai }
428352f7f91STakashi Iwai 
429c4a58c30STakashi Iwai /*
430dda42bd0STakashi Iwai  * snd_hda_parse_nid_path - parse the widget path from the given nid to
431dda42bd0STakashi Iwai  * the target nid
432dda42bd0STakashi Iwai  * @codec: the HDA codec
433dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
434dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
435dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication
436dda42bd0STakashi Iwai  * @path: the path object to store the result
437dda42bd0STakashi Iwai  *
438dda42bd0STakashi Iwai  * Returns true if a matching path is found.
439dda42bd0STakashi Iwai  *
440dda42bd0STakashi Iwai  * The parsing behavior depends on parameters:
441352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4423ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4433ca529d3STakashi Iwai  * with the given value are evaluated.
4443ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4453ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4463ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
447352f7f91STakashi Iwai  */
448c4a58c30STakashi Iwai static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4493ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
450352f7f91STakashi Iwai 			    struct nid_path *path)
451352f7f91STakashi Iwai {
4523ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
453352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
454352f7f91STakashi Iwai 		path->depth++;
455352f7f91STakashi Iwai 		return true;
456352f7f91STakashi Iwai 	}
457352f7f91STakashi Iwai 	return false;
458352f7f91STakashi Iwai }
459352f7f91STakashi Iwai 
460dda42bd0STakashi Iwai /**
461dda42bd0STakashi Iwai  * snd_hda_add_new_path - parse the path between the given NIDs and
462dda42bd0STakashi Iwai  * add to the path list
463dda42bd0STakashi Iwai  * @codec: the HDA codec
464dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
465dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
466dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
467dda42bd0STakashi Iwai  *
468dda42bd0STakashi Iwai  * If no valid path is found, returns NULL.
469352f7f91STakashi Iwai  */
470352f7f91STakashi Iwai struct nid_path *
471352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4723ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
473352f7f91STakashi Iwai {
474352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
475352f7f91STakashi Iwai 	struct nid_path *path;
476352f7f91STakashi Iwai 
477352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
478352f7f91STakashi Iwai 		return NULL;
479352f7f91STakashi Iwai 
480f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4813ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
482f5172a7eSTakashi Iwai 	if (path)
483f5172a7eSTakashi Iwai 		return path;
484f5172a7eSTakashi Iwai 
485352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
486352f7f91STakashi Iwai 	if (!path)
487352f7f91STakashi Iwai 		return NULL;
488352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4893ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
490352f7f91STakashi Iwai 		return path;
491352f7f91STakashi Iwai 	/* push back */
492352f7f91STakashi Iwai 	spec->paths.used--;
493352f7f91STakashi Iwai 	return NULL;
494352f7f91STakashi Iwai }
4952698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
496352f7f91STakashi Iwai 
497980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
498980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
499980428ceSTakashi Iwai {
500980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
501980428ceSTakashi Iwai 	if (!path)
502980428ceSTakashi Iwai 		return;
503980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
504980428ceSTakashi Iwai }
505980428ceSTakashi Iwai 
5063690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
5073690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
5083690739bSTakashi Iwai {
5093690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5103690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
5113690739bSTakashi Iwai 
5123690739bSTakashi Iwai 	if (!list)
5133690739bSTakashi Iwai 		return 0;
5143690739bSTakashi Iwai 	for (; *list; list += 2)
5153690739bSTakashi Iwai 		if (*list == pin)
5163690739bSTakashi Iwai 			return list[1];
5173690739bSTakashi Iwai 	return 0;
5183690739bSTakashi Iwai }
5193690739bSTakashi Iwai 
520352f7f91STakashi Iwai /* look for an empty DAC slot */
521352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
522352f7f91STakashi Iwai 			      bool is_digital)
523352f7f91STakashi Iwai {
524352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
525352f7f91STakashi Iwai 	bool cap_digital;
526352f7f91STakashi Iwai 	int i;
527352f7f91STakashi Iwai 
528352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
529352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
530352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
531352f7f91STakashi Iwai 			continue;
532352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
533352f7f91STakashi Iwai 		if (is_digital != cap_digital)
534352f7f91STakashi Iwai 			continue;
535352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
536352f7f91STakashi Iwai 			return nid;
537352f7f91STakashi Iwai 	}
538352f7f91STakashi Iwai 	return 0;
539352f7f91STakashi Iwai }
540352f7f91STakashi Iwai 
541352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
542352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
543352f7f91STakashi Iwai {
544352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
545352f7f91STakashi Iwai 	val |= chs << 16;
546352f7f91STakashi Iwai 	return val;
547352f7f91STakashi Iwai }
548352f7f91STakashi Iwai 
54999a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
55099a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
55199a5592dSDavid Henningsson {
55299a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
55399a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
55499a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
55599a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
55699a5592dSDavid Henningsson }
55799a5592dSDavid Henningsson 
558352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
559352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
560352f7f91STakashi Iwai 				       struct nid_path *path)
561352f7f91STakashi Iwai {
562352f7f91STakashi Iwai 	int i;
563352f7f91STakashi Iwai 
564352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
565352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
566352f7f91STakashi Iwai 			return path->path[i];
567352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
568352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
569352f7f91STakashi Iwai 			return path->path[i];
570352f7f91STakashi Iwai 	}
571352f7f91STakashi Iwai 	return 0;
572352f7f91STakashi Iwai }
573352f7f91STakashi Iwai 
574352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
575352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
576352f7f91STakashi Iwai 				      struct nid_path *path)
577352f7f91STakashi Iwai {
578a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
579352f7f91STakashi Iwai 	int i;
580352f7f91STakashi Iwai 
581352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
582a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
583a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
584a1114a8cSTakashi Iwai 			continue;
585a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
586a1114a8cSTakashi Iwai 			return nid;
587352f7f91STakashi Iwai 	}
588352f7f91STakashi Iwai 	return 0;
589352f7f91STakashi Iwai }
590352f7f91STakashi Iwai 
591352f7f91STakashi Iwai /*
592352f7f91STakashi Iwai  * path activation / deactivation
593352f7f91STakashi Iwai  */
594352f7f91STakashi Iwai 
595352f7f91STakashi Iwai /* can have the amp-in capability? */
596352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
597352f7f91STakashi Iwai {
598352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
599352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
600352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
601352f7f91STakashi Iwai 
602352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
603352f7f91STakashi Iwai 		return false;
604352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
605352f7f91STakashi Iwai 		return false;
606352f7f91STakashi Iwai 	return true;
607352f7f91STakashi Iwai }
608352f7f91STakashi Iwai 
609352f7f91STakashi Iwai /* can have the amp-out capability? */
610352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
611352f7f91STakashi Iwai {
612352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
613352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
614352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
615352f7f91STakashi Iwai 
616352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
617352f7f91STakashi Iwai 		return false;
618352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
619352f7f91STakashi Iwai 		return false;
620352f7f91STakashi Iwai 	return true;
621352f7f91STakashi Iwai }
622352f7f91STakashi Iwai 
623352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
624352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6257dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
626352f7f91STakashi Iwai {
627352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
628e6feb5d0STakashi Iwai 	int type = get_wcaps_type(get_wcaps(codec, nid));
629a9c2dfc8STakashi Iwai 	const struct nid_path *path;
630352f7f91STakashi Iwai 	int i, n;
631352f7f91STakashi Iwai 
6327639a06cSTakashi Iwai 	if (nid == codec->core.afg)
6335ccf835cSTakashi Iwai 		return true;
6345ccf835cSTakashi Iwai 
635a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, n, path) {
636352f7f91STakashi Iwai 		if (!path->active)
637352f7f91STakashi Iwai 			continue;
638967b1307STakashi Iwai 		if (codec->power_save_node) {
639e6feb5d0STakashi Iwai 			if (!path->stream_enabled)
640e6feb5d0STakashi Iwai 				continue;
641e6feb5d0STakashi Iwai 			/* ignore unplugged paths except for DAC/ADC */
6426b275b14STakashi Iwai 			if (!(path->pin_enabled || path->pin_fixed) &&
643e6feb5d0STakashi Iwai 			    type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
644e6feb5d0STakashi Iwai 				continue;
645e6feb5d0STakashi Iwai 		}
646352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
647352f7f91STakashi Iwai 			if (path->path[i] == nid) {
6489d2b48f7STakashi Iwai 				if (dir == HDA_OUTPUT || idx == -1 ||
6499d2b48f7STakashi Iwai 				    path->idx[i] == idx)
650352f7f91STakashi Iwai 					return true;
651352f7f91STakashi Iwai 				break;
652352f7f91STakashi Iwai 			}
653352f7f91STakashi Iwai 		}
654352f7f91STakashi Iwai 	}
655352f7f91STakashi Iwai 	return false;
656352f7f91STakashi Iwai }
657352f7f91STakashi Iwai 
658b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
659b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
6609d2b48f7STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, -1)
661b1b9fbd0STakashi Iwai 
662352f7f91STakashi Iwai /* get the default amp value for the target state */
663352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6648999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
665352f7f91STakashi Iwai {
666352f7f91STakashi Iwai 	unsigned int val = 0;
667352f7f91STakashi Iwai 
668352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
669352f7f91STakashi Iwai 		/* set to 0dB */
670352f7f91STakashi Iwai 		if (enable)
671352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
672352f7f91STakashi Iwai 	}
673f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
674352f7f91STakashi Iwai 		if (!enable)
675352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
676352f7f91STakashi Iwai 	}
677352f7f91STakashi Iwai 	return val;
678352f7f91STakashi Iwai }
679352f7f91STakashi Iwai 
680cc261738STakashi Iwai /* is this a stereo widget or a stereo-to-mono mix? */
681cc261738STakashi Iwai static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
682cc261738STakashi Iwai {
683cc261738STakashi Iwai 	unsigned int wcaps = get_wcaps(codec, nid);
684cc261738STakashi Iwai 	hda_nid_t conn;
685cc261738STakashi Iwai 
686cc261738STakashi Iwai 	if (wcaps & AC_WCAP_STEREO)
687cc261738STakashi Iwai 		return true;
688cc261738STakashi Iwai 	if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
689cc261738STakashi Iwai 		return false;
690cc261738STakashi Iwai 	if (snd_hda_get_num_conns(codec, nid) != 1)
691cc261738STakashi Iwai 		return false;
692cc261738STakashi Iwai 	if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
693cc261738STakashi Iwai 		return false;
694cc261738STakashi Iwai 	return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
695cc261738STakashi Iwai }
696cc261738STakashi Iwai 
697352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
698352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
699352f7f91STakashi Iwai {
7008999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
7018999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
702ef403edbSTakashi Iwai 
703cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
704352f7f91STakashi Iwai 		snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
705ef403edbSTakashi Iwai 	else
706ef403edbSTakashi Iwai 		snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
707ef403edbSTakashi Iwai }
708ef403edbSTakashi Iwai 
709ef403edbSTakashi Iwai /* update the amp, doing in stereo or mono depending on NID */
710ef403edbSTakashi Iwai static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
711ef403edbSTakashi Iwai 		      unsigned int mask, unsigned int val)
712ef403edbSTakashi Iwai {
713cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
714ef403edbSTakashi Iwai 		return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
715ef403edbSTakashi Iwai 						mask, val);
716ef403edbSTakashi Iwai 	else
717ef403edbSTakashi Iwai 		return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
718ef403edbSTakashi Iwai 						mask, val);
719352f7f91STakashi Iwai }
720352f7f91STakashi Iwai 
7218999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
7228999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
7238999bf0aSTakashi Iwai  */
7248999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
7258999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
7268999bf0aSTakashi Iwai 					   unsigned int caps)
727352f7f91STakashi Iwai {
7288999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
7298999bf0aSTakashi Iwai 
730f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
7318999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
7328999bf0aSTakashi Iwai 			mask &= ~0x80;
7338999bf0aSTakashi Iwai 	}
7348999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
7358999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
7368999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
7378999bf0aSTakashi Iwai 			mask &= ~0x7f;
7388999bf0aSTakashi Iwai 	}
7398999bf0aSTakashi Iwai 	return mask;
7408999bf0aSTakashi Iwai }
7418999bf0aSTakashi Iwai 
7428999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
7438999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
7448999bf0aSTakashi Iwai {
7458999bf0aSTakashi Iwai 	unsigned int caps;
7468999bf0aSTakashi Iwai 	unsigned int mask, val;
7478999bf0aSTakashi Iwai 
7488999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
7498999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
7508999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
7518999bf0aSTakashi Iwai 	if (!mask)
7528999bf0aSTakashi Iwai 		return;
7538999bf0aSTakashi Iwai 
7548999bf0aSTakashi Iwai 	val &= mask;
755ef403edbSTakashi Iwai 	update_amp(codec, nid, dir, idx, mask, val);
756352f7f91STakashi Iwai }
757352f7f91STakashi Iwai 
758e7fdd527STakashi Iwai static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
759e7fdd527STakashi Iwai 				   int dir, int idx, int idx_to_check,
760e7fdd527STakashi Iwai 				   bool enable)
761e7fdd527STakashi Iwai {
762e7fdd527STakashi Iwai 	/* check whether the given amp is still used by others */
763e7fdd527STakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
764e7fdd527STakashi Iwai 		return;
765e7fdd527STakashi Iwai 	activate_amp(codec, nid, dir, idx, idx_to_check, enable);
766e7fdd527STakashi Iwai }
767e7fdd527STakashi Iwai 
768352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
769352f7f91STakashi Iwai 			     int i, bool enable)
770352f7f91STakashi Iwai {
771352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
772352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
773e7fdd527STakashi Iwai 	check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
774352f7f91STakashi Iwai }
775352f7f91STakashi Iwai 
776352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
777352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
778352f7f91STakashi Iwai {
779352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
780ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
781352f7f91STakashi Iwai 	int n, nums, idx;
782352f7f91STakashi Iwai 	int type;
783352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
784352f7f91STakashi Iwai 
785ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
7860de7d835SDan Carpenter 	if (nums < 0)
7870de7d835SDan Carpenter 		return;
788352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
789352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
790352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
791352f7f91STakashi Iwai 		nums = 1;
792352f7f91STakashi Iwai 		idx = 0;
793352f7f91STakashi Iwai 	} else
794352f7f91STakashi Iwai 		idx = path->idx[i];
795352f7f91STakashi Iwai 
796352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
797352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
798352f7f91STakashi Iwai 
799352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
800352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
801352f7f91STakashi Iwai 	 */
802352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
803e7fdd527STakashi Iwai 		if (n != idx) {
804e7fdd527STakashi Iwai 			if (conn[n] != spec->mixer_merge_nid)
805352f7f91STakashi Iwai 				continue;
806e7fdd527STakashi Iwai 			/* when aamix is disabled, force to off */
807e7fdd527STakashi Iwai 			if (!add_aamix) {
808e7fdd527STakashi Iwai 				activate_amp(codec, nid, HDA_INPUT, n, n, false);
809e7fdd527STakashi Iwai 				continue;
810e7fdd527STakashi Iwai 			}
811e7fdd527STakashi Iwai 		}
812e7fdd527STakashi Iwai 		check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
813352f7f91STakashi Iwai 	}
814352f7f91STakashi Iwai }
815352f7f91STakashi Iwai 
816c7fabbc5SRandy Dunlap /* sync power of each widget in the given path */
817e6feb5d0STakashi Iwai static hda_nid_t path_power_update(struct hda_codec *codec,
818e6feb5d0STakashi Iwai 				   struct nid_path *path,
819e6feb5d0STakashi Iwai 				   bool allow_powerdown)
820e6feb5d0STakashi Iwai {
821e6feb5d0STakashi Iwai 	hda_nid_t nid, changed = 0;
82250fd4987STakashi Iwai 	int i, state, power;
823e6feb5d0STakashi Iwai 
824e6feb5d0STakashi Iwai 	for (i = 0; i < path->depth; i++) {
825e6feb5d0STakashi Iwai 		nid = path->path[i];
8262206dc94STakashi Iwai 		if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
8272206dc94STakashi Iwai 			continue;
8287639a06cSTakashi Iwai 		if (nid == codec->core.afg)
8295ccf835cSTakashi Iwai 			continue;
830e6feb5d0STakashi Iwai 		if (!allow_powerdown || is_active_nid_for_any(codec, nid))
831e6feb5d0STakashi Iwai 			state = AC_PWRST_D0;
832e6feb5d0STakashi Iwai 		else
833e6feb5d0STakashi Iwai 			state = AC_PWRST_D3;
83450fd4987STakashi Iwai 		power = snd_hda_codec_read(codec, nid, 0,
83550fd4987STakashi Iwai 					   AC_VERB_GET_POWER_STATE, 0);
83650fd4987STakashi Iwai 		if (power != (state | (state << 4))) {
837e6feb5d0STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
838e6feb5d0STakashi Iwai 					    AC_VERB_SET_POWER_STATE, state);
839e6feb5d0STakashi Iwai 			changed = nid;
84048f4b3a2STakashi Iwai 			/* all known codecs seem to be capable to handl
84148f4b3a2STakashi Iwai 			 * widgets state even in D3, so far.
84248f4b3a2STakashi Iwai 			 * if any new codecs need to restore the widget
84348f4b3a2STakashi Iwai 			 * states after D0 transition, call the function
84448f4b3a2STakashi Iwai 			 * below.
84548f4b3a2STakashi Iwai 			 */
84648f4b3a2STakashi Iwai #if 0 /* disabled */
847d545a57cSTakashi Iwai 			if (state == AC_PWRST_D0)
848d545a57cSTakashi Iwai 				snd_hdac_regmap_sync_node(&codec->core, nid);
84948f4b3a2STakashi Iwai #endif
850e6feb5d0STakashi Iwai 		}
851e6feb5d0STakashi Iwai 	}
852e6feb5d0STakashi Iwai 	return changed;
853e6feb5d0STakashi Iwai }
854e6feb5d0STakashi Iwai 
855e6feb5d0STakashi Iwai /* do sync with the last power state change */
856e6feb5d0STakashi Iwai static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
857e6feb5d0STakashi Iwai {
858e6feb5d0STakashi Iwai 	if (nid) {
859e6feb5d0STakashi Iwai 		msleep(10);
860e6feb5d0STakashi Iwai 		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
861e6feb5d0STakashi Iwai 	}
862e6feb5d0STakashi Iwai }
863e6feb5d0STakashi Iwai 
864dda42bd0STakashi Iwai /**
865dda42bd0STakashi Iwai  * snd_hda_activate_path - activate or deactivate the given path
866dda42bd0STakashi Iwai  * @codec: the HDA codec
867dda42bd0STakashi Iwai  * @path: the path to activate/deactivate
868dda42bd0STakashi Iwai  * @enable: flag to activate or not
869dda42bd0STakashi Iwai  * @add_aamix: enable the input from aamix NID
870dda42bd0STakashi Iwai  *
871dda42bd0STakashi Iwai  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
872352f7f91STakashi Iwai  */
873352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
874352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
875352f7f91STakashi Iwai {
87655196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
877352f7f91STakashi Iwai 	int i;
878352f7f91STakashi Iwai 
879c7cd0ef6STakashi Iwai 	path->active = enable;
880352f7f91STakashi Iwai 
881e6feb5d0STakashi Iwai 	/* make sure the widget is powered up */
882967b1307STakashi Iwai 	if (enable && (spec->power_down_unused || codec->power_save_node))
883967b1307STakashi Iwai 		path_power_update(codec, path, codec->power_save_node);
884e6feb5d0STakashi Iwai 
885352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
88655196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
887e6feb5d0STakashi Iwai 
888352f7f91STakashi Iwai 		if (enable && path->multi[i])
889401caff7STakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
890352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
891352f7f91STakashi Iwai 					    path->idx[i]);
892352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
893352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
894352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
895352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
896352f7f91STakashi Iwai 	}
897352f7f91STakashi Iwai }
8982698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
899352f7f91STakashi Iwai 
90055196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
90155196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
90255196fffSTakashi Iwai {
90355196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
90455196fffSTakashi Iwai 
905967b1307STakashi Iwai 	if (!(spec->power_down_unused || codec->power_save_node) || path->active)
90655196fffSTakashi Iwai 		return;
907e6feb5d0STakashi Iwai 	sync_power_state_change(codec, path_power_update(codec, path, true));
90855196fffSTakashi Iwai }
90955196fffSTakashi Iwai 
910d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
911d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
912d5a9f1bbSTakashi Iwai {
913d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
914d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
915d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
916d5a9f1bbSTakashi Iwai 		return;
91705909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
91805909d5cSTakashi Iwai 		return;
919468ac413STakashi Iwai 	if (codec->inv_eapd)
920468ac413STakashi Iwai 		enable = !enable;
921401caff7STakashi Iwai 	snd_hda_codec_write_cache(codec, pin, 0,
922d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
923d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
924d5a9f1bbSTakashi Iwai }
925d5a9f1bbSTakashi Iwai 
9263e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
9273e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
9283e367f15STakashi Iwai {
9293e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
9303e367f15STakashi Iwai 	if (path)
9313e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
9323e367f15STakashi Iwai }
9333e367f15STakashi Iwai 
934352f7f91STakashi Iwai 
935352f7f91STakashi Iwai /*
936352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
937352f7f91STakashi Iwai  */
938352f7f91STakashi Iwai 
9397eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
9407eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
941698f5ee3STakashi Iwai static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
942698f5ee3STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
943bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
944bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
9457eebffd3STakashi Iwai 
946352f7f91STakashi Iwai enum {
947352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
948352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
949352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
950352f7f91STakashi Iwai };
951352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
952352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
9537eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
9547eebffd3STakashi Iwai 	{
9557eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9567eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
9577eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
9587eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
9597eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
9607eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
9617eebffd3STakashi Iwai 	},
962bc2eee29STakashi Iwai 	{
963bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
964bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
965698f5ee3STakashi Iwai 		.get = hda_gen_bind_mute_get,
966bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
967bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
968bc2eee29STakashi Iwai 	},
969352f7f91STakashi Iwai };
970352f7f91STakashi Iwai 
971352f7f91STakashi Iwai /* add dynamic controls from template */
972a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
973a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
974352f7f91STakashi Iwai 		       int cidx, unsigned long val)
975352f7f91STakashi Iwai {
976352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
977352f7f91STakashi Iwai 
97812c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
979352f7f91STakashi Iwai 	if (!knew)
980a35bd1e3STakashi Iwai 		return NULL;
981352f7f91STakashi Iwai 	knew->index = cidx;
982352f7f91STakashi Iwai 	if (get_amp_nid_(val))
983352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
984*e65bf997SJaroslav Kysela 	if (knew->access == 0)
985*e65bf997SJaroslav Kysela 		knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
986352f7f91STakashi Iwai 	knew->private_value = val;
987a35bd1e3STakashi Iwai 	return knew;
988352f7f91STakashi Iwai }
989352f7f91STakashi Iwai 
990352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
991352f7f91STakashi Iwai 				const char *pfx, const char *dir,
992352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
993352f7f91STakashi Iwai {
994975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
995352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
996a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
997a35bd1e3STakashi Iwai 		return -ENOMEM;
998a35bd1e3STakashi Iwai 	return 0;
999352f7f91STakashi Iwai }
1000352f7f91STakashi Iwai 
1001352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1002352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1003352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1004352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1005352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1006352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1007352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1008352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1009352f7f91STakashi Iwai 
1010352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1011352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
1012352f7f91STakashi Iwai {
1013352f7f91STakashi Iwai 	unsigned int val;
1014352f7f91STakashi Iwai 	if (!path)
1015352f7f91STakashi Iwai 		return 0;
1016352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
1017352f7f91STakashi Iwai 	if (!val)
1018352f7f91STakashi Iwai 		return 0;
1019352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1020352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1021352f7f91STakashi Iwai }
1022352f7f91STakashi Iwai 
1023352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
1024352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1025352f7f91STakashi Iwai 			       int type)
1026352f7f91STakashi Iwai {
1027352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
1028352f7f91STakashi Iwai 	if (path) {
1029352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1030352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1031352f7f91STakashi Iwai 			chs = 3; /* stereo */
1032352f7f91STakashi Iwai 	}
1033352f7f91STakashi Iwai 	return chs;
1034352f7f91STakashi Iwai }
1035352f7f91STakashi Iwai 
1036352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1037352f7f91STakashi Iwai 			  struct nid_path *path)
1038352f7f91STakashi Iwai {
1039352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1040352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1041352f7f91STakashi Iwai }
1042352f7f91STakashi Iwai 
1043352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
1044352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1045352f7f91STakashi Iwai  */
1046352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1047352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
1048352f7f91STakashi Iwai {
1049352f7f91STakashi Iwai 	unsigned int val;
1050352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
1051352f7f91STakashi Iwai 
1052352f7f91STakashi Iwai 	if (!path)
1053352f7f91STakashi Iwai 		return 0;
1054352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
1055352f7f91STakashi Iwai 	if (!val)
1056352f7f91STakashi Iwai 		return 0;
1057352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1058352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
1059352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
1060352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
1061352f7f91STakashi Iwai 		if (nums > 1) {
1062352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
1063352f7f91STakashi Iwai 			val |= nums << 19;
1064352f7f91STakashi Iwai 		}
1065352f7f91STakashi Iwai 	}
1066352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1067352f7f91STakashi Iwai }
1068352f7f91STakashi Iwai 
1069352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1070352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1071352f7f91STakashi Iwai {
1072352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1073352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1074352f7f91STakashi Iwai }
1075352f7f91STakashi Iwai 
10767eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1077bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10787eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10797eebffd3STakashi Iwai {
10807eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10817eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10827eebffd3STakashi Iwai 
10837eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10847eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10857eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10867eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10877eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10887eebffd3STakashi Iwai 	}
1089bc2eee29STakashi Iwai }
10907eebffd3STakashi Iwai 
1091bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1092bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1093bc2eee29STakashi Iwai {
1094bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
10957eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
10967eebffd3STakashi Iwai }
10977eebffd3STakashi Iwai 
1098698f5ee3STakashi Iwai /*
1099698f5ee3STakashi Iwai  * Bound mute controls
1100698f5ee3STakashi Iwai  */
1101698f5ee3STakashi Iwai #define AMP_VAL_IDX_SHIFT	19
1102698f5ee3STakashi Iwai #define AMP_VAL_IDX_MASK	(0x0f<<19)
1103698f5ee3STakashi Iwai 
1104698f5ee3STakashi Iwai static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
1105698f5ee3STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1106698f5ee3STakashi Iwai {
1107698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1108698f5ee3STakashi Iwai 	unsigned long pval;
1109698f5ee3STakashi Iwai 	int err;
1110698f5ee3STakashi Iwai 
1111698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1112698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1113698f5ee3STakashi Iwai 	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1114698f5ee3STakashi Iwai 	err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1115698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1116698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1117698f5ee3STakashi Iwai 	return err;
1118698f5ee3STakashi Iwai }
1119698f5ee3STakashi Iwai 
1120bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1121bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1122bc2eee29STakashi Iwai {
1123698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1124698f5ee3STakashi Iwai 	unsigned long pval;
1125698f5ee3STakashi Iwai 	int i, indices, err = 0, change = 0;
1126698f5ee3STakashi Iwai 
1127bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1128698f5ee3STakashi Iwai 
1129698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1130698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1131698f5ee3STakashi Iwai 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1132698f5ee3STakashi Iwai 	for (i = 0; i < indices; i++) {
1133698f5ee3STakashi Iwai 		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1134698f5ee3STakashi Iwai 			(i << AMP_VAL_IDX_SHIFT);
1135698f5ee3STakashi Iwai 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1136698f5ee3STakashi Iwai 		if (err < 0)
1137698f5ee3STakashi Iwai 			break;
1138698f5ee3STakashi Iwai 		change |= err;
1139698f5ee3STakashi Iwai 	}
1140698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1141698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1142698f5ee3STakashi Iwai 	return err < 0 ? err : change;
1143bc2eee29STakashi Iwai }
1144bc2eee29STakashi Iwai 
1145247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1146247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1147247d85eeSTakashi Iwai {
1148247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1149247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1150247d85eeSTakashi Iwai }
1151247d85eeSTakashi Iwai 
1152352f7f91STakashi Iwai static const char * const channel_name[4] = {
1153352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1154352f7f91STakashi Iwai };
1155352f7f91STakashi Iwai 
1156352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1157247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1158247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1159352f7f91STakashi Iwai {
1160247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1161352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1162352f7f91STakashi Iwai 
1163352f7f91STakashi Iwai 	*index = 0;
1164352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
11659f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1166247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1167352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1168352f7f91STakashi Iwai 
1169352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1170352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1171352f7f91STakashi Iwai 	 */
1172352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
11739f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1174352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1175352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1176352f7f91STakashi Iwai 
1177247d85eeSTakashi Iwai 	/* multi-io channels */
1178247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1179247d85eeSTakashi Iwai 		return channel_name[ch];
1180247d85eeSTakashi Iwai 
1181352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1182352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1183247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1184247d85eeSTakashi Iwai 		 * don't name it as Speaker
1185247d85eeSTakashi Iwai 		 */
1186247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1187247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1188247d85eeSTakashi Iwai 			break;
1189352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1190352f7f91STakashi Iwai 			return "Speaker";
1191352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1192352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1193352f7f91STakashi Iwai 		break;
1194352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1195247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1196247d85eeSTakashi Iwai 		 * don't name it as Headphone
1197247d85eeSTakashi Iwai 		 */
1198247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1199247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1200247d85eeSTakashi Iwai 			break;
1201352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1202352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1203352f7f91STakashi Iwai 			break;
1204352f7f91STakashi Iwai 		*index = ch;
1205352f7f91STakashi Iwai 		return "Headphone";
120603ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
120703ad6a8cSDavid Henningsson 		/* This deals with the case where we have two DACs and
120803ad6a8cSDavid Henningsson 		 * one LO, one HP and one Speaker */
120903ad6a8cSDavid Henningsson 		if (!ch && cfg->speaker_outs && cfg->hp_outs) {
121003ad6a8cSDavid Henningsson 			bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
121103ad6a8cSDavid Henningsson 			bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
121203ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
121303ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
121403ad6a8cSDavid Henningsson 			if (hp_lo_shared)
121503ad6a8cSDavid Henningsson 				return "Headphone+LO";
121603ad6a8cSDavid Henningsson 			if (spk_lo_shared)
121703ad6a8cSDavid Henningsson 				return "Speaker+LO";
121803ad6a8cSDavid Henningsson 		}
1219247d85eeSTakashi Iwai 	}
1220247d85eeSTakashi Iwai 
1221247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1222352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
12233abb4f4dSDavid Henningsson 		return "Line Out";
1224247d85eeSTakashi Iwai 
1225352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1226352f7f91STakashi Iwai 		snd_BUG();
1227352f7f91STakashi Iwai 		return "PCM";
1228352f7f91STakashi Iwai 	}
1229352f7f91STakashi Iwai 
1230352f7f91STakashi Iwai 	return channel_name[ch];
1231352f7f91STakashi Iwai }
1232352f7f91STakashi Iwai 
1233352f7f91STakashi Iwai /*
1234352f7f91STakashi Iwai  * Parse output paths
1235352f7f91STakashi Iwai  */
1236352f7f91STakashi Iwai 
1237352f7f91STakashi Iwai /* badness definition */
1238352f7f91STakashi Iwai enum {
1239352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1240352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1241352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1242352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1243352f7f91STakashi Iwai 	/* No possible multi-ios */
12441d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1245352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1246352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1247352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1248352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1249352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1250352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
125155a63d4dSTakashi Iwai 	/* No independent HP possible */
1252bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1253352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1254352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1255352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1256352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1257352f7f91STakashi Iwai 	/* Volume widget is shared */
1258352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1259352f7f91STakashi Iwai };
1260352f7f91STakashi Iwai 
12610e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1262352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1263352f7f91STakashi Iwai  *
1264352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1265352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1266352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1267352f7f91STakashi Iwai  */
12680e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1269352f7f91STakashi Iwai {
1270d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1271352f7f91STakashi Iwai 	hda_nid_t nid;
1272352f7f91STakashi Iwai 	unsigned int val;
1273352f7f91STakashi Iwai 	int badness = 0;
1274352f7f91STakashi Iwai 
1275352f7f91STakashi Iwai 	if (!path)
1276352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
12770e614dd0STakashi Iwai 
12780e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
12790e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
12800e614dd0STakashi Iwai 		return 0; /* already evaluated */
12810e614dd0STakashi Iwai 
1282352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1283352f7f91STakashi Iwai 	if (nid) {
1284352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1285d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1286d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1287352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1288352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1289352f7f91STakashi Iwai 		else
1290352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1291352f7f91STakashi Iwai 	} else
1292352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1293352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1294352f7f91STakashi Iwai 	if (nid) {
1295352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1296352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1297352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1298352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1299352f7f91STakashi Iwai 		else
1300352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1301352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1302352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1303352f7f91STakashi Iwai 		else
1304352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1305352f7f91STakashi Iwai 	} else
1306352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1307352f7f91STakashi Iwai 	return badness;
1308352f7f91STakashi Iwai }
1309352f7f91STakashi Iwai 
131098bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1311352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1312352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1313352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1314352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1315352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1316352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1317352f7f91STakashi Iwai };
13182698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1319352f7f91STakashi Iwai 
132098bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1321352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1322352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1323352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1324352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1325352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1326352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1327352f7f91STakashi Iwai };
13282698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1329352f7f91STakashi Iwai 
13307385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
13317385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
13327385df61STakashi Iwai {
13337385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
13347385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
13357385df61STakashi Iwai 
13367385df61STakashi Iwai 	if (cfg->line_outs > idx)
13377385df61STakashi Iwai 		return spec->private_dac_nids[idx];
13387385df61STakashi Iwai 	idx -= cfg->line_outs;
13397385df61STakashi Iwai 	if (spec->multi_ios > idx)
13407385df61STakashi Iwai 		return spec->multi_io[idx].dac;
13417385df61STakashi Iwai 	return 0;
13427385df61STakashi Iwai }
13437385df61STakashi Iwai 
13447385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
13457385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
13467385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
13477385df61STakashi Iwai {
13487385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
13497385df61STakashi Iwai }
13507385df61STakashi Iwai 
1351352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1352352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1353352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1354196c1766STakashi Iwai 			   int *path_idx,
1355352f7f91STakashi Iwai 			   const struct badness_table *bad)
1356352f7f91STakashi Iwai {
1357352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1358352f7f91STakashi Iwai 	int i, j;
1359352f7f91STakashi Iwai 	int badness = 0;
1360352f7f91STakashi Iwai 	hda_nid_t dac;
1361352f7f91STakashi Iwai 
1362352f7f91STakashi Iwai 	if (!num_outs)
1363352f7f91STakashi Iwai 		return 0;
1364352f7f91STakashi Iwai 
1365352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
13660c8c0f56STakashi Iwai 		struct nid_path *path;
1367352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
13681e0b5286STakashi Iwai 
1369242d990cSTakashi Iwai 		if (!spec->obey_preferred_dacs) {
13700e614dd0STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, path_idx[i]);
13710e614dd0STakashi Iwai 			if (path) {
13720e614dd0STakashi Iwai 				badness += assign_out_path_ctls(codec, path);
13731e0b5286STakashi Iwai 				continue;
13741e0b5286STakashi Iwai 			}
1375242d990cSTakashi Iwai 		}
13761e0b5286STakashi Iwai 
13773690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
13783690739bSTakashi Iwai 		if (dacs[i]) {
13793690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
13803690739bSTakashi Iwai 				badness += bad->shared_primary;
1381242d990cSTakashi Iwai 		} else if (spec->obey_preferred_dacs) {
1382242d990cSTakashi Iwai 			badness += BAD_NO_PRIMARY_DAC;
13833690739bSTakashi Iwai 		}
13843690739bSTakashi Iwai 
13853690739bSTakashi Iwai 		if (!dacs[i])
1386352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1387352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1388980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1389352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1390352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1391352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1392352f7f91STakashi Iwai 					dacs[j] = 0;
1393980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1394196c1766STakashi Iwai 					path_idx[j] = 0;
1395352f7f91STakashi Iwai 					break;
1396352f7f91STakashi Iwai 				}
1397352f7f91STakashi Iwai 			}
1398352f7f91STakashi Iwai 		}
1399352f7f91STakashi Iwai 		dac = dacs[i];
1400352f7f91STakashi Iwai 		if (!dac) {
14017385df61STakashi Iwai 			if (num_outs > 2)
14027385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
14037385df61STakashi Iwai 			if (!dac)
14047385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
14057385df61STakashi Iwai 			if (!dac)
14067385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1407352f7f91STakashi Iwai 			if (dac) {
1408352f7f91STakashi Iwai 				if (!i)
1409352f7f91STakashi Iwai 					badness += bad->shared_primary;
1410352f7f91STakashi Iwai 				else if (i == 1)
1411352f7f91STakashi Iwai 					badness += bad->shared_surr;
1412352f7f91STakashi Iwai 				else
1413352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1414352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1415352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1416352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1417352f7f91STakashi Iwai 			} else if (!i)
1418352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1419352f7f91STakashi Iwai 			else
1420352f7f91STakashi Iwai 				badness += bad->no_dac;
1421352f7f91STakashi Iwai 		}
14221fa335b0STakashi Iwai 		if (!dac)
14231fa335b0STakashi Iwai 			continue;
14243ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1425117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1426b3a8c745STakashi Iwai 			/* try with aamix */
14273ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1428b3a8c745STakashi Iwai 		}
14291fa335b0STakashi Iwai 		if (!path) {
1430352f7f91STakashi Iwai 			dac = dacs[i] = 0;
14311fa335b0STakashi Iwai 			badness += bad->no_dac;
14321fa335b0STakashi Iwai 		} else {
14334e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1434e1284af7STakashi Iwai 			path->active = true;
1435196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
14360e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1437e1284af7STakashi Iwai 		}
1438352f7f91STakashi Iwai 	}
1439352f7f91STakashi Iwai 
1440352f7f91STakashi Iwai 	return badness;
1441352f7f91STakashi Iwai }
1442352f7f91STakashi Iwai 
1443352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1444352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1445352f7f91STakashi Iwai {
1446352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1447352f7f91STakashi Iwai 	int i;
1448352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1449352f7f91STakashi Iwai 
1450352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1451352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1452352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1453352f7f91STakashi Iwai 			continue;
1454352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1455352f7f91STakashi Iwai 			if (nid_found)
1456352f7f91STakashi Iwai 				return 0;
1457352f7f91STakashi Iwai 			nid_found = nid;
1458352f7f91STakashi Iwai 		}
1459352f7f91STakashi Iwai 	}
1460352f7f91STakashi Iwai 	return nid_found;
1461352f7f91STakashi Iwai }
1462352f7f91STakashi Iwai 
1463352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1464352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1465352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1466352f7f91STakashi Iwai {
1467352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1468352f7f91STakashi Iwai 
1469352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1470352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1471352f7f91STakashi Iwai 		return false;
1472352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1473352f7f91STakashi Iwai 		return false;
1474352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1475352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1476352f7f91STakashi Iwai 		return false;
1477352f7f91STakashi Iwai 	return true;
1478352f7f91STakashi Iwai }
1479352f7f91STakashi Iwai 
1480e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1481e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1482e22aab7dSTakashi Iwai {
1483e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1484e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1485e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1486e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1487e22aab7dSTakashi Iwai 	int type, i;
1488e22aab7dSTakashi Iwai 	int num_pins = 0;
1489e22aab7dSTakashi Iwai 
1490e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1491e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1492e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1493e22aab7dSTakashi Iwai 				continue;
1494e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1495e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1496e22aab7dSTakashi Iwai 				num_pins++;
1497e22aab7dSTakashi Iwai 		}
1498e22aab7dSTakashi Iwai 	}
1499e22aab7dSTakashi Iwai 	return num_pins;
1500e22aab7dSTakashi Iwai }
1501e22aab7dSTakashi Iwai 
1502352f7f91STakashi Iwai /*
1503352f7f91STakashi Iwai  * multi-io helper
1504352f7f91STakashi Iwai  *
1505352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1506352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1507352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1508352f7f91STakashi Iwai  * the badness value.
1509352f7f91STakashi Iwai  */
1510352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1511352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1512e22aab7dSTakashi Iwai 			  bool hardwired)
1513352f7f91STakashi Iwai {
1514352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1515352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1516e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1517352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1518352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1519352f7f91STakashi Iwai 	int badness = 0;
15200e614dd0STakashi Iwai 	struct nid_path *path;
1521352f7f91STakashi Iwai 
1522352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1523352f7f91STakashi Iwai 	if (old_pins >= 2)
1524352f7f91STakashi Iwai 		goto end_fill;
1525352f7f91STakashi Iwai 
1526e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1527352f7f91STakashi Iwai 	if (num_pins < 2)
1528352f7f91STakashi Iwai 		goto end_fill;
1529352f7f91STakashi Iwai 
1530352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1531352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1532352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1533352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1534352f7f91STakashi Iwai 
1535352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1536352f7f91STakashi Iwai 				continue;
1537352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1538352f7f91STakashi Iwai 				continue;
1539352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1540352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1541352f7f91STakashi Iwai 					break;
1542352f7f91STakashi Iwai 			}
1543352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1544352f7f91STakashi Iwai 				continue;
1545352f7f91STakashi Iwai 
1546352f7f91STakashi Iwai 			if (hardwired)
1547352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1548352f7f91STakashi Iwai 			else if (!dac)
1549352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1550352f7f91STakashi Iwai 			if (!dac) {
1551352f7f91STakashi Iwai 				badness++;
1552352f7f91STakashi Iwai 				continue;
1553352f7f91STakashi Iwai 			}
15543ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
15553ca529d3STakashi Iwai 						    -spec->mixer_nid);
15560c8c0f56STakashi Iwai 			if (!path) {
1557352f7f91STakashi Iwai 				badness++;
1558352f7f91STakashi Iwai 				continue;
1559352f7f91STakashi Iwai 			}
15604e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1561352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1562352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1563196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1564196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1565352f7f91STakashi Iwai 			spec->multi_ios++;
1566352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1567352f7f91STakashi Iwai 				break;
1568352f7f91STakashi Iwai 		}
1569352f7f91STakashi Iwai 	}
1570352f7f91STakashi Iwai  end_fill:
1571352f7f91STakashi Iwai 	if (badness)
1572352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1573352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1574352f7f91STakashi Iwai 		if (hardwired)
1575352f7f91STakashi Iwai 			return 1; /* nothing found */
1576352f7f91STakashi Iwai 		else
1577352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1578352f7f91STakashi Iwai 	}
1579352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1580352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1581352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1582352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1583352f7f91STakashi Iwai 		return badness;
1584352f7f91STakashi Iwai 	}
1585352f7f91STakashi Iwai 
1586352f7f91STakashi Iwai 	/* assign volume and mute controls */
15870e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
15880e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
15890e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
15900e614dd0STakashi Iwai 	}
1591352f7f91STakashi Iwai 
1592352f7f91STakashi Iwai 	return badness;
1593352f7f91STakashi Iwai }
1594352f7f91STakashi Iwai 
1595352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1596352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1597196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1598352f7f91STakashi Iwai {
1599b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1600352f7f91STakashi Iwai 	int i;
1601352f7f91STakashi Iwai 	bool found = false;
1602352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
16030c8c0f56STakashi Iwai 		struct nid_path *path;
1604352f7f91STakashi Iwai 		hda_nid_t dac;
1605352f7f91STakashi Iwai 		if (dacs[i])
1606352f7f91STakashi Iwai 			continue;
1607352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1608352f7f91STakashi Iwai 		if (!dac)
1609352f7f91STakashi Iwai 			continue;
16103ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
16113ca529d3STakashi Iwai 					    -spec->mixer_nid);
1612117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
16133ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
16140c8c0f56STakashi Iwai 		if (path) {
1615352f7f91STakashi Iwai 			dacs[i] = dac;
1616352f7f91STakashi Iwai 			found = true;
16174e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1618e1284af7STakashi Iwai 			path->active = true;
1619196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1620352f7f91STakashi Iwai 		}
1621352f7f91STakashi Iwai 	}
1622352f7f91STakashi Iwai 	return found;
1623352f7f91STakashi Iwai }
1624352f7f91STakashi Iwai 
1625e7fdd527STakashi Iwai static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1626e7fdd527STakashi Iwai {
1627e7fdd527STakashi Iwai 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1628e7fdd527STakashi Iwai 		spec->aamix_out_paths[2];
1629e7fdd527STakashi Iwai }
1630e7fdd527STakashi Iwai 
1631c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1632c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1633c30aa7b2STakashi Iwai {
16343ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1635c30aa7b2STakashi Iwai 	struct nid_path *path;
16365ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1637c30aa7b2STakashi Iwai 
1638c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
16393ca529d3STakashi Iwai 	if (!path || !path->depth ||
16403ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1641c30aa7b2STakashi Iwai 		return 0;
16425ead56f2STakashi Iwai 	path_dac = path->path[0];
16435ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1644f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1645f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1646f87498b6STakashi Iwai 	if (!path) {
16475ead56f2STakashi Iwai 		if (dac != path_dac)
16485ead56f2STakashi Iwai 			dac = path_dac;
1649f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1650f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1651f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1652f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
16535ead56f2STakashi Iwai 		else
16545ead56f2STakashi Iwai 			dac = 0;
1655f87498b6STakashi Iwai 		if (dac)
1656f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
16573ca529d3STakashi Iwai 						    spec->mixer_nid);
1658f87498b6STakashi Iwai 	}
1659c30aa7b2STakashi Iwai 	if (!path)
1660c30aa7b2STakashi Iwai 		return 0;
16614e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1662c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
16636b275b14STakashi Iwai 	path->pin_fixed = true; /* static route */
1664c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1665c30aa7b2STakashi Iwai }
1666c30aa7b2STakashi Iwai 
166755a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
166855a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
166955a63d4dSTakashi Iwai {
167055a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
167155a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
167255a63d4dSTakashi Iwai 	struct nid_path *path;
167355a63d4dSTakashi Iwai 	int i, idx;
167455a63d4dSTakashi Iwai 
167555a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
167655a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
167755a63d4dSTakashi Iwai 	else
167855a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
167955a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
168055a63d4dSTakashi Iwai 	if (!path)
168155a63d4dSTakashi Iwai 		return false;
168255a63d4dSTakashi Iwai 
168355a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
168455a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
168555a63d4dSTakashi Iwai 		return true;
168655a63d4dSTakashi Iwai 
168755a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
168855a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
168955a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
169055a63d4dSTakashi Iwai 			break;
169155a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
169255a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
169355a63d4dSTakashi Iwai 			return false;
169455a63d4dSTakashi Iwai 	}
169555a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
169655a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
169755a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
169855a63d4dSTakashi Iwai 			return false;
169955a63d4dSTakashi Iwai 	}
170055a63d4dSTakashi Iwai 
170155a63d4dSTakashi Iwai 	return true;
170255a63d4dSTakashi Iwai }
170355a63d4dSTakashi Iwai 
1704a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1705a07a949bSTakashi Iwai  * shared dac pointed by the paths
1706a07a949bSTakashi Iwai  */
1707a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1708a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1709a07a949bSTakashi Iwai {
1710a07a949bSTakashi Iwai 	struct nid_path *path;
1711a07a949bSTakashi Iwai 	int i;
1712a07a949bSTakashi Iwai 
1713a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1714a07a949bSTakashi Iwai 		if (dacs[i])
1715a07a949bSTakashi Iwai 			continue;
1716a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1717a07a949bSTakashi Iwai 		if (!path)
1718a07a949bSTakashi Iwai 			continue;
1719a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1720a07a949bSTakashi Iwai 	}
1721a07a949bSTakashi Iwai }
1722a07a949bSTakashi Iwai 
1723352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1724352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1725352f7f91STakashi Iwai 			      bool fill_hardwired,
1726352f7f91STakashi Iwai 			      bool fill_mio_first)
1727352f7f91STakashi Iwai {
1728352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1729352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1730352f7f91STakashi Iwai 	int i, err, badness;
1731352f7f91STakashi Iwai 
1732352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1733352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1734352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1735352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1736352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1737352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1738352f7f91STakashi Iwai 	spec->multi_ios = 0;
1739352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1740cd5be3f9STakashi Iwai 
1741cd5be3f9STakashi Iwai 	/* clear path indices */
1742cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1743cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1744cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1745cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1746cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1747c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1748cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1749cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1750cd5be3f9STakashi Iwai 
1751352f7f91STakashi Iwai 	badness = 0;
1752352f7f91STakashi Iwai 
1753352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1754352f7f91STakashi Iwai 	if (fill_hardwired) {
1755352f7f91STakashi Iwai 		bool mapped;
1756352f7f91STakashi Iwai 		do {
1757352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1758352f7f91STakashi Iwai 					     cfg->line_out_pins,
1759196c1766STakashi Iwai 					     spec->private_dac_nids,
1760196c1766STakashi Iwai 					     spec->out_paths);
1761352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1762352f7f91STakashi Iwai 					      cfg->hp_pins,
1763196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1764196c1766STakashi Iwai 					      spec->hp_paths);
1765352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1766352f7f91STakashi Iwai 					      cfg->speaker_pins,
1767196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1768196c1766STakashi Iwai 					      spec->speaker_paths);
1769da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1770da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1771352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1772e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1773352f7f91STakashi Iwai 				if (!err)
1774352f7f91STakashi Iwai 					mapped = true;
1775352f7f91STakashi Iwai 			}
1776352f7f91STakashi Iwai 		} while (mapped);
1777352f7f91STakashi Iwai 	}
1778352f7f91STakashi Iwai 
1779352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1780196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
178198bd1115STakashi Iwai 				   spec->main_out_badness);
1782352f7f91STakashi Iwai 
1783da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1784352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1785352f7f91STakashi Iwai 		/* try to fill multi-io first */
1786e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1787352f7f91STakashi Iwai 		if (err < 0)
1788352f7f91STakashi Iwai 			return err;
1789352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1790352f7f91STakashi Iwai 	}
1791352f7f91STakashi Iwai 
1792352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1793352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1794352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1795196c1766STakashi Iwai 				      spec->hp_paths,
179698bd1115STakashi Iwai 				      spec->extra_out_badness);
1797352f7f91STakashi Iwai 		if (err < 0)
1798352f7f91STakashi Iwai 			return err;
1799352f7f91STakashi Iwai 		badness += err;
1800352f7f91STakashi Iwai 	}
1801352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1802352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1803352f7f91STakashi Iwai 				      cfg->speaker_pins,
1804352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1805196c1766STakashi Iwai 				      spec->speaker_paths,
180698bd1115STakashi Iwai 				      spec->extra_out_badness);
1807352f7f91STakashi Iwai 		if (err < 0)
1808352f7f91STakashi Iwai 			return err;
1809352f7f91STakashi Iwai 		badness += err;
1810352f7f91STakashi Iwai 	}
1811da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1812da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1813e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1814352f7f91STakashi Iwai 		if (err < 0)
1815352f7f91STakashi Iwai 			return err;
1816352f7f91STakashi Iwai 		badness += err;
1817352f7f91STakashi Iwai 	}
1818e22aab7dSTakashi Iwai 
1819c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1820c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1821c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1822c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1823c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1824c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1825c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1826c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1827c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1828c30aa7b2STakashi Iwai 	}
1829c30aa7b2STakashi Iwai 
1830da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1831da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1832e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1833e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1834352f7f91STakashi Iwai 
1835a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1836a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1837a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1838a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1839a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1840a07a949bSTakashi Iwai 		else {
1841a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1842a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1843a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1844a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1845a07a949bSTakashi Iwai 		}
1846a07a949bSTakashi Iwai 	}
1847a07a949bSTakashi Iwai 
1848a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1849c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1850a07a949bSTakashi Iwai 
1851352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1852352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1853352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1854352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1855352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1856352f7f91STakashi Iwai 		spec->multi_ios = 0;
1857352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1858352f7f91STakashi Iwai 	}
1859352f7f91STakashi Iwai 
186055a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
186155a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
186255a63d4dSTakashi Iwai 
1863a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1864a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1865a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1866a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1867a07a949bSTakashi Iwai 				   spec->hp_paths);
1868a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1869a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1870a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1871a07a949bSTakashi Iwai 				   spec->speaker_paths);
1872a07a949bSTakashi Iwai 
1873352f7f91STakashi Iwai 	return badness;
1874352f7f91STakashi Iwai }
1875352f7f91STakashi Iwai 
1876352f7f91STakashi Iwai #define DEBUG_BADNESS
1877352f7f91STakashi Iwai 
1878352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1879d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1880d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1881352f7f91STakashi Iwai #else
1882d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1883d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1884352f7f91STakashi Iwai #endif
1885352f7f91STakashi Iwai 
1886a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1887a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1888a769409cSTakashi Iwai 				      const char *pfx, int idx)
1889352f7f91STakashi Iwai {
1890a769409cSTakashi Iwai 	struct nid_path *path;
1891a769409cSTakashi Iwai 
1892a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1893a769409cSTakashi Iwai 	if (path)
18944e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1895a769409cSTakashi Iwai }
1896a769409cSTakashi Iwai 
1897a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1898a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1899a769409cSTakashi Iwai {
1900a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1901a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1902a769409cSTakashi Iwai 	int i;
1903a769409cSTakashi Iwai 
1904a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1905352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1906708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1907352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1908352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1909352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1910a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1911a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1912a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1913a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1914352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1915352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1916352f7f91STakashi Iwai 			      spec->multi_ios,
1917352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1918352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1919a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1920a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1921a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1922a769409cSTakashi Iwai 	if (cfg->hp_outs)
1923352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1924352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1925708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1926352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1927352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1928352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1929352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1930a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1931a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1932a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1933352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1934352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1935352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1936352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1937352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1938352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1939352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1940a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1941a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1942a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1943a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1944352f7f91STakashi Iwai }
1945a769409cSTakashi Iwai #else
1946a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1947a769409cSTakashi Iwai #endif
1948352f7f91STakashi Iwai 
1949352f7f91STakashi Iwai /* find all available DACs of the codec */
1950352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1951352f7f91STakashi Iwai {
1952352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
19537639a06cSTakashi Iwai 	hda_nid_t nid;
1954352f7f91STakashi Iwai 
1955352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1956352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
19577639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
1958352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1959352f7f91STakashi Iwai 			continue;
1960352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
19614e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1962352f7f91STakashi Iwai 			break;
1963352f7f91STakashi Iwai 		}
1964352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1965352f7f91STakashi Iwai 	}
1966352f7f91STakashi Iwai }
1967352f7f91STakashi Iwai 
1968352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1969352f7f91STakashi Iwai {
1970352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1971352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1972352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
19739314a581STakashi Iwai 	unsigned int val;
1974352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1975352f7f91STakashi Iwai 	int badness;
1976352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1977352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1978352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1979352f7f91STakashi Iwai 
1980352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1981352f7f91STakashi Iwai 	if (!best_cfg)
1982352f7f91STakashi Iwai 		return -ENOMEM;
1983352f7f91STakashi Iwai 	*best_cfg = *cfg;
1984352f7f91STakashi Iwai 
1985352f7f91STakashi Iwai 	for (;;) {
1986352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1987352f7f91STakashi Iwai 					     fill_mio_first);
1988352f7f91STakashi Iwai 		if (badness < 0) {
1989352f7f91STakashi Iwai 			kfree(best_cfg);
1990352f7f91STakashi Iwai 			return badness;
1991352f7f91STakashi Iwai 		}
1992352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1993352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1994352f7f91STakashi Iwai 			      badness);
1995a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1996352f7f91STakashi Iwai 		if (badness < best_badness) {
1997352f7f91STakashi Iwai 			best_badness = badness;
1998352f7f91STakashi Iwai 			*best_cfg = *cfg;
1999352f7f91STakashi Iwai 			best_wired = fill_hardwired;
2000352f7f91STakashi Iwai 			best_mio = fill_mio_first;
2001352f7f91STakashi Iwai 		}
2002352f7f91STakashi Iwai 		if (!badness)
2003352f7f91STakashi Iwai 			break;
2004352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
2005352f7f91STakashi Iwai 		if (!fill_mio_first)
2006352f7f91STakashi Iwai 			continue;
2007352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
2008352f7f91STakashi Iwai 		if (!fill_hardwired)
2009352f7f91STakashi Iwai 			continue;
2010352f7f91STakashi Iwai 		if (hp_spk_swapped)
2011352f7f91STakashi Iwai 			break;
2012352f7f91STakashi Iwai 		hp_spk_swapped = true;
2013352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
2014352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2015352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
2016352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
2017352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2018352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
2019352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
2020352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2021352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
2022352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
2023352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
2024352f7f91STakashi Iwai 			fill_hardwired = true;
2025352f7f91STakashi Iwai 			continue;
2026352f7f91STakashi Iwai 		}
2027352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
2028352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2029352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
2030352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
2031352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2032352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
2033352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
2034352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2035352f7f91STakashi Iwai 			cfg->hp_outs = 0;
2036352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2037352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
2038352f7f91STakashi Iwai 			fill_hardwired = true;
2039352f7f91STakashi Iwai 			continue;
2040352f7f91STakashi Iwai 		}
2041352f7f91STakashi Iwai 		break;
2042352f7f91STakashi Iwai 	}
2043352f7f91STakashi Iwai 
2044352f7f91STakashi Iwai 	if (badness) {
20450c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
2046352f7f91STakashi Iwai 		*cfg = *best_cfg;
2047352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
2048352f7f91STakashi Iwai 	}
2049352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2050352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
2051a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
2052352f7f91STakashi Iwai 
2053352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
2054352f7f91STakashi Iwai 		struct nid_path *path;
2055196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2056352f7f91STakashi Iwai 		if (path)
2057352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2058d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
20597a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
20607a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
2061d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
206251cdc8b6STakashi Sakamoto 				spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
2063d89c6c0cSTakashi Iwai 		}
2064352f7f91STakashi Iwai 	}
2065352f7f91STakashi Iwai 
20669314a581STakashi Iwai 	/* set initial pinctl targets */
20679314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
20689314a581STakashi Iwai 		val = PIN_HP;
20699314a581STakashi Iwai 	else
20709314a581STakashi Iwai 		val = PIN_OUT;
20719314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
20729314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
20739314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
20749314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
20759314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
20769314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
20779314a581STakashi Iwai 				cfg->speaker_pins, val);
20789314a581STakashi Iwai 	}
20799314a581STakashi Iwai 
208055a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
208155a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
208255a63d4dSTakashi Iwai 		spec->indep_hp = 0;
208355a63d4dSTakashi Iwai 
2084352f7f91STakashi Iwai 	kfree(best_cfg);
2085352f7f91STakashi Iwai 	return 0;
2086352f7f91STakashi Iwai }
2087352f7f91STakashi Iwai 
2088352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
2089352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
2090352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
2091352f7f91STakashi Iwai {
2092352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2093352f7f91STakashi Iwai 	int i, err, noutputs;
2094352f7f91STakashi Iwai 
2095352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
2096352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2097352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
2098352f7f91STakashi Iwai 
2099352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
2100352f7f91STakashi Iwai 		const char *name;
2101352f7f91STakashi Iwai 		int index;
2102352f7f91STakashi Iwai 		struct nid_path *path;
2103352f7f91STakashi Iwai 
2104196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2105352f7f91STakashi Iwai 		if (!path)
2106352f7f91STakashi Iwai 			continue;
2107247d85eeSTakashi Iwai 
2108247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2109352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2110352f7f91STakashi Iwai 			/* Center/LFE */
2111352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2112352f7f91STakashi Iwai 			if (err < 0)
2113352f7f91STakashi Iwai 				return err;
2114352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2115352f7f91STakashi Iwai 			if (err < 0)
2116352f7f91STakashi Iwai 				return err;
2117247d85eeSTakashi Iwai 		} else {
2118247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2119247d85eeSTakashi Iwai 			if (err < 0)
2120247d85eeSTakashi Iwai 				return err;
2121247d85eeSTakashi Iwai 		}
2122247d85eeSTakashi Iwai 
2123247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2124247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2125352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2126352f7f91STakashi Iwai 			if (err < 0)
2127352f7f91STakashi Iwai 				return err;
2128352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2129352f7f91STakashi Iwai 			if (err < 0)
2130352f7f91STakashi Iwai 				return err;
2131352f7f91STakashi Iwai 		} else {
2132352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2133352f7f91STakashi Iwai 			if (err < 0)
2134352f7f91STakashi Iwai 				return err;
2135352f7f91STakashi Iwai 		}
2136352f7f91STakashi Iwai 	}
2137352f7f91STakashi Iwai 	return 0;
2138352f7f91STakashi Iwai }
2139352f7f91STakashi Iwai 
2140c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2141196c1766STakashi Iwai 			    const char *pfx, int cidx)
2142352f7f91STakashi Iwai {
2143352f7f91STakashi Iwai 	struct nid_path *path;
2144352f7f91STakashi Iwai 	int err;
2145352f7f91STakashi Iwai 
2146196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2147352f7f91STakashi Iwai 	if (!path)
2148352f7f91STakashi Iwai 		return 0;
2149352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2150352f7f91STakashi Iwai 	if (err < 0)
2151352f7f91STakashi Iwai 		return err;
2152352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2153352f7f91STakashi Iwai 	if (err < 0)
2154352f7f91STakashi Iwai 		return err;
2155352f7f91STakashi Iwai 	return 0;
2156352f7f91STakashi Iwai }
2157352f7f91STakashi Iwai 
2158352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2159352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2160196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2161352f7f91STakashi Iwai {
2162c2c80383STakashi Iwai 	int i;
2163352f7f91STakashi Iwai 
2164352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2165c2c80383STakashi Iwai 		const char *name;
2166975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2167c2c80383STakashi Iwai 		int err, idx = 0;
2168c2c80383STakashi Iwai 
2169c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2170c2c80383STakashi Iwai 			name = "Bass Speaker";
2171c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2172c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2173352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2174c2c80383STakashi Iwai 			name = tmp;
2175352f7f91STakashi Iwai 		} else {
2176c2c80383STakashi Iwai 			name = pfx;
2177c2c80383STakashi Iwai 			idx = i;
2178352f7f91STakashi Iwai 		}
2179c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2180352f7f91STakashi Iwai 		if (err < 0)
2181352f7f91STakashi Iwai 			return err;
2182352f7f91STakashi Iwai 	}
2183352f7f91STakashi Iwai 	return 0;
2184352f7f91STakashi Iwai }
2185352f7f91STakashi Iwai 
2186352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2187352f7f91STakashi Iwai {
2188352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2189352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2190196c1766STakashi Iwai 				 spec->hp_paths,
2191352f7f91STakashi Iwai 				 "Headphone");
2192352f7f91STakashi Iwai }
2193352f7f91STakashi Iwai 
2194352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2195352f7f91STakashi Iwai {
2196352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2197352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2198196c1766STakashi Iwai 				 spec->speaker_paths,
2199352f7f91STakashi Iwai 				 "Speaker");
2200352f7f91STakashi Iwai }
2201352f7f91STakashi Iwai 
2202352f7f91STakashi Iwai /*
220338cf6f1aSTakashi Iwai  * independent HP controls
220438cf6f1aSTakashi Iwai  */
220538cf6f1aSTakashi Iwai 
22061a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
22071a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
220838cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
220938cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
221038cf6f1aSTakashi Iwai {
221138cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
221238cf6f1aSTakashi Iwai }
221338cf6f1aSTakashi Iwai 
221438cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
221538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
221638cf6f1aSTakashi Iwai {
221738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
221838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
221938cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
222038cf6f1aSTakashi Iwai 	return 0;
222138cf6f1aSTakashi Iwai }
222238cf6f1aSTakashi Iwai 
2223a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2224a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2225a1e908edSTakashi Iwai 			       int out_type);
2226a1e908edSTakashi Iwai 
222738cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
222838cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
222938cf6f1aSTakashi Iwai {
223038cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
223138cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
223238cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
223338cf6f1aSTakashi Iwai 	int ret = 0;
223438cf6f1aSTakashi Iwai 
223538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
223638cf6f1aSTakashi Iwai 	if (spec->active_streams) {
223738cf6f1aSTakashi Iwai 		ret = -EBUSY;
223838cf6f1aSTakashi Iwai 		goto unlock;
223938cf6f1aSTakashi Iwai 	}
224038cf6f1aSTakashi Iwai 
224138cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2242a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2243a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2244a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2245a1e908edSTakashi Iwai 		else
2246a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2247a1e908edSTakashi Iwai 
2248a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2249a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2250a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2251a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2252a1e908edSTakashi Iwai 						   spec->out_paths[0],
2253a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2254a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2255a1e908edSTakashi Iwai 			else
2256a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2257a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2258a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2259a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2260a1e908edSTakashi Iwai 		}
2261a1e908edSTakashi Iwai 
226238cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
226338cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2264a1e908edSTakashi Iwai 			*dacp = 0;
226538cf6f1aSTakashi Iwai 		else
2266a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
226792603c59STakashi Iwai 
2268963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
226938cf6f1aSTakashi Iwai 		ret = 1;
227038cf6f1aSTakashi Iwai 	}
227138cf6f1aSTakashi Iwai  unlock:
227238cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
227338cf6f1aSTakashi Iwai 	return ret;
227438cf6f1aSTakashi Iwai }
227538cf6f1aSTakashi Iwai 
227638cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
227738cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
227838cf6f1aSTakashi Iwai 	.name = "Independent HP",
227938cf6f1aSTakashi Iwai 	.info = indep_hp_info,
228038cf6f1aSTakashi Iwai 	.get = indep_hp_get,
228138cf6f1aSTakashi Iwai 	.put = indep_hp_put,
228238cf6f1aSTakashi Iwai };
228338cf6f1aSTakashi Iwai 
228438cf6f1aSTakashi Iwai 
228538cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
228638cf6f1aSTakashi Iwai {
228738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2288a1e908edSTakashi Iwai 	hda_nid_t dac;
228938cf6f1aSTakashi Iwai 
229038cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
229138cf6f1aSTakashi Iwai 		return 0;
2292a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2293a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2294a1e908edSTakashi Iwai 	else
2295a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2296a1e908edSTakashi Iwai 	if (!dac) {
229738cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
229838cf6f1aSTakashi Iwai 		return 0;
229938cf6f1aSTakashi Iwai 	}
230038cf6f1aSTakashi Iwai 
230138cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2302a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
230338cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
230438cf6f1aSTakashi Iwai 		return -ENOMEM;
230538cf6f1aSTakashi Iwai 	return 0;
230638cf6f1aSTakashi Iwai }
230738cf6f1aSTakashi Iwai 
230838cf6f1aSTakashi Iwai /*
2309352f7f91STakashi Iwai  * channel mode enum control
2310352f7f91STakashi Iwai  */
2311352f7f91STakashi Iwai 
2312352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2313352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2314352f7f91STakashi Iwai {
2315352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2316352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2317a07a949bSTakashi Iwai 	int chs;
2318352f7f91STakashi Iwai 
2319352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2320352f7f91STakashi Iwai 	uinfo->count = 1;
2321352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2322352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2323352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2324a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2325a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2326352f7f91STakashi Iwai 	return 0;
2327352f7f91STakashi Iwai }
2328352f7f91STakashi Iwai 
2329352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2330352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2331352f7f91STakashi Iwai {
2332352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2333352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2334a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2335a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2336352f7f91STakashi Iwai 	return 0;
2337352f7f91STakashi Iwai }
2338352f7f91STakashi Iwai 
2339196c1766STakashi Iwai static inline struct nid_path *
2340196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2341196c1766STakashi Iwai {
2342196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2343196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2344196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2345196c1766STakashi Iwai }
2346196c1766STakashi Iwai 
2347a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2348a5cc2509STakashi Iwai 
234965033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
235065033cc8STakashi Iwai  * used for output paths
235165033cc8STakashi Iwai  */
235265033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
235365033cc8STakashi Iwai {
235465033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
235565033cc8STakashi Iwai }
235665033cc8STakashi Iwai 
2357352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2358352f7f91STakashi Iwai {
2359352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2360352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2361352f7f91STakashi Iwai 	struct nid_path *path;
2362352f7f91STakashi Iwai 
2363196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2364352f7f91STakashi Iwai 	if (!path)
2365352f7f91STakashi Iwai 		return -EINVAL;
2366352f7f91STakashi Iwai 
2367352f7f91STakashi Iwai 	if (path->active == output)
2368352f7f91STakashi Iwai 		return 0;
2369352f7f91STakashi Iwai 
2370352f7f91STakashi Iwai 	if (output) {
23712c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
237265033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2373d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2374352f7f91STakashi Iwai 	} else {
2375d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
237665033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
23772c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
237855196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2379352f7f91STakashi Iwai 	}
2380a365fed9STakashi Iwai 
2381a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2382a5cc2509STakashi Iwai 	update_automute_all(codec);
2383a365fed9STakashi Iwai 
2384352f7f91STakashi Iwai 	return 0;
2385352f7f91STakashi Iwai }
2386352f7f91STakashi Iwai 
2387352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2388352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2389352f7f91STakashi Iwai {
2390352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2391352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2392352f7f91STakashi Iwai 	int i, ch;
2393352f7f91STakashi Iwai 
2394352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2395352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2396352f7f91STakashi Iwai 		return -EINVAL;
2397a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2398352f7f91STakashi Iwai 		return 0;
2399a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2400352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2401352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2402352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2403352f7f91STakashi Iwai 					  spec->const_channel_count);
2404352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2405352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2406352f7f91STakashi Iwai 	return 1;
2407352f7f91STakashi Iwai }
2408352f7f91STakashi Iwai 
2409352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2410352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2411352f7f91STakashi Iwai 	.name = "Channel Mode",
2412352f7f91STakashi Iwai 	.info = ch_mode_info,
2413352f7f91STakashi Iwai 	.get = ch_mode_get,
2414352f7f91STakashi Iwai 	.put = ch_mode_put,
2415352f7f91STakashi Iwai };
2416352f7f91STakashi Iwai 
2417352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2418352f7f91STakashi Iwai {
2419352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2420352f7f91STakashi Iwai 
2421352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
242212c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2423352f7f91STakashi Iwai 			return -ENOMEM;
2424352f7f91STakashi Iwai 	}
2425352f7f91STakashi Iwai 	return 0;
2426352f7f91STakashi Iwai }
2427352f7f91STakashi Iwai 
2428352f7f91STakashi Iwai /*
2429c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2430c30aa7b2STakashi Iwai  */
2431c30aa7b2STakashi Iwai 
2432c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2433c30aa7b2STakashi Iwai 
2434c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2435c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2436c30aa7b2STakashi Iwai {
2437c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2438c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2439c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2440c30aa7b2STakashi Iwai 	return 0;
2441c30aa7b2STakashi Iwai }
2442c30aa7b2STakashi Iwai 
2443c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2444a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2445a1e908edSTakashi Iwai 			       int out_type)
2446c30aa7b2STakashi Iwai {
2447a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2448c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2449c30aa7b2STakashi Iwai 
2450c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2451c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2452c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2453c30aa7b2STakashi Iwai 		return;
2454a1e908edSTakashi Iwai 
2455a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2456a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2457a1e908edSTakashi Iwai 	 */
2458a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2459a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2460a1e908edSTakashi Iwai 		do_mix = false;
2461a1e908edSTakashi Iwai 
2462c30aa7b2STakashi Iwai 	if (do_mix) {
2463c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2464c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
246555196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2466c30aa7b2STakashi Iwai 	} else {
246765033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
246865033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
246955196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2470c30aa7b2STakashi Iwai 	}
2471c30aa7b2STakashi Iwai }
2472c30aa7b2STakashi Iwai 
2473e7fdd527STakashi Iwai /* re-initialize the output paths; only called from loopback_mixing_put() */
2474e7fdd527STakashi Iwai static void update_output_paths(struct hda_codec *codec, int num_outs,
2475e7fdd527STakashi Iwai 				const int *paths)
2476e7fdd527STakashi Iwai {
2477e7fdd527STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2478e7fdd527STakashi Iwai 	struct nid_path *path;
2479e7fdd527STakashi Iwai 	int i;
2480e7fdd527STakashi Iwai 
2481e7fdd527STakashi Iwai 	for (i = 0; i < num_outs; i++) {
2482e7fdd527STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2483e7fdd527STakashi Iwai 		if (path)
2484e7fdd527STakashi Iwai 			snd_hda_activate_path(codec, path, path->active,
2485e7fdd527STakashi Iwai 					      spec->aamix_mode);
2486e7fdd527STakashi Iwai 	}
2487e7fdd527STakashi Iwai }
2488e7fdd527STakashi Iwai 
2489c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2490c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2491c30aa7b2STakashi Iwai {
2492c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2493c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2494e7fdd527STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2495c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2496c30aa7b2STakashi Iwai 
2497c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2498c30aa7b2STakashi Iwai 		return 0;
2499c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2500e7fdd527STakashi Iwai 	if (has_aamix_out_paths(spec)) {
2501c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->out_paths[0],
2502a1e908edSTakashi Iwai 				   spec->aamix_out_paths[0],
2503e7fdd527STakashi Iwai 				   cfg->line_out_type);
2504c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->hp_paths[0],
2505a1e908edSTakashi Iwai 				   spec->aamix_out_paths[1],
2506a1e908edSTakashi Iwai 				   AUTO_PIN_HP_OUT);
2507c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2508a1e908edSTakashi Iwai 				   spec->aamix_out_paths[2],
2509a1e908edSTakashi Iwai 				   AUTO_PIN_SPEAKER_OUT);
2510e7fdd527STakashi Iwai 	} else {
2511e7fdd527STakashi Iwai 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2512e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2513e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2514e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2515e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->speaker_outs,
2516e7fdd527STakashi Iwai 					    spec->speaker_paths);
2517e7fdd527STakashi Iwai 	}
2518c30aa7b2STakashi Iwai 	return 1;
2519c30aa7b2STakashi Iwai }
2520c30aa7b2STakashi Iwai 
2521c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2522c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2523c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2524c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2525c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2526c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2527c30aa7b2STakashi Iwai };
2528c30aa7b2STakashi Iwai 
2529c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2530c30aa7b2STakashi Iwai {
2531c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2532c30aa7b2STakashi Iwai 
2533c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2534c30aa7b2STakashi Iwai 		return 0;
2535c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2536c30aa7b2STakashi Iwai 		return -ENOMEM;
2537a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2538c30aa7b2STakashi Iwai 	return 0;
2539c30aa7b2STakashi Iwai }
2540c30aa7b2STakashi Iwai 
2541c30aa7b2STakashi Iwai /*
2542352f7f91STakashi Iwai  * shared headphone/mic handling
2543352f7f91STakashi Iwai  */
2544352f7f91STakashi Iwai 
2545352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2546352f7f91STakashi Iwai 
2547352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2548967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2549352f7f91STakashi Iwai {
2550352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2551967303daSTakashi Iwai 	bool as_mic;
2552352f7f91STakashi Iwai 	unsigned int val;
2553967303daSTakashi Iwai 	hda_nid_t pin;
2554967303daSTakashi Iwai 
2555967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2556967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2557967303daSTakashi Iwai 
2558967303daSTakashi Iwai 	if (!force) {
2559967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2560967303daSTakashi Iwai 		if (as_mic) {
2561967303daSTakashi Iwai 			if (val & PIN_IN)
2562967303daSTakashi Iwai 				return;
2563967303daSTakashi Iwai 		} else {
2564967303daSTakashi Iwai 			if (val & PIN_OUT)
2565967303daSTakashi Iwai 				return;
2566967303daSTakashi Iwai 		}
2567967303daSTakashi Iwai 	}
2568352f7f91STakashi Iwai 
2569352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2570967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2571967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2572967303daSTakashi Iwai 	 */
2573352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2574352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2575352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2576352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
25777594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2578967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2579352f7f91STakashi Iwai 	}
2580352f7f91STakashi Iwai 
25818ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2582967303daSTakashi Iwai 		if (as_mic)
2583967303daSTakashi Iwai 			val |= PIN_IN;
2584967303daSTakashi Iwai 		else
2585967303daSTakashi Iwai 			val = PIN_HP;
25862c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2587963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
25888ba955ceSTakashi Iwai 	}
2589352f7f91STakashi Iwai }
2590352f7f91STakashi Iwai 
2591352f7f91STakashi Iwai /* create a shared input with the headphone out */
2592967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2593352f7f91STakashi Iwai {
2594352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2595352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2596352f7f91STakashi Iwai 	unsigned int defcfg;
2597352f7f91STakashi Iwai 	hda_nid_t nid;
2598352f7f91STakashi Iwai 
2599967303daSTakashi Iwai 	if (!spec->hp_mic) {
2600967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2601352f7f91STakashi Iwai 			return 0;
2602967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2603967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2604967303daSTakashi Iwai 		 */
2605967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2606967303daSTakashi Iwai 			return 0;
2607967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2608352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2609352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2610352f7f91STakashi Iwai 				return 0;
2611967303daSTakashi Iwai 		}
2612967303daSTakashi Iwai 	}
2613352f7f91STakashi Iwai 
2614967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2615967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2616967303daSTakashi Iwai 		return 0;
2617967303daSTakashi Iwai 
2618967303daSTakashi Iwai 	nid = 0;
2619967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2620967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2621967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2622967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2623967303daSTakashi Iwai 	if (!nid)
2624967303daSTakashi Iwai 		return 0;
2625352f7f91STakashi Iwai 
2626352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2627352f7f91STakashi Iwai 		return 0; /* no input */
2628352f7f91STakashi Iwai 
2629967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2630967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2631cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2632967303daSTakashi Iwai 	cfg->num_inputs++;
2633967303daSTakashi Iwai 	spec->hp_mic = 1;
2634967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2635967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2636967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
26374e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2638352f7f91STakashi Iwai 	return 0;
2639352f7f91STakashi Iwai }
2640352f7f91STakashi Iwai 
2641978e77e7STakashi Iwai /*
2642978e77e7STakashi Iwai  * output jack mode
2643978e77e7STakashi Iwai  */
26445f171baaSTakashi Iwai 
26455f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
26465f171baaSTakashi Iwai 
26475f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
26485f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
26495f171baaSTakashi Iwai };
26505f171baaSTakashi Iwai 
2651978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2652978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2653978e77e7STakashi Iwai {
26545f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2655978e77e7STakashi Iwai }
2656978e77e7STakashi Iwai 
2657978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2658978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2659978e77e7STakashi Iwai {
2660978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2661978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2662978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2663978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2664978e77e7STakashi Iwai 	else
2665978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2666978e77e7STakashi Iwai 	return 0;
2667978e77e7STakashi Iwai }
2668978e77e7STakashi Iwai 
2669978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2670978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2671978e77e7STakashi Iwai {
2672978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2673978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2674978e77e7STakashi Iwai 	unsigned int val;
2675978e77e7STakashi Iwai 
2676978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2677978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2678978e77e7STakashi Iwai 		return 0;
2679978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2680978e77e7STakashi Iwai 	return 1;
2681978e77e7STakashi Iwai }
2682978e77e7STakashi Iwai 
2683978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2684978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2685978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2686978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2687978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2688978e77e7STakashi Iwai };
2689978e77e7STakashi Iwai 
2690978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2691978e77e7STakashi Iwai {
2692978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2693a9c2dfc8STakashi Iwai 	const struct snd_kcontrol_new *kctl;
2694978e77e7STakashi Iwai 	int i;
2695978e77e7STakashi Iwai 
2696a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->kctls, i, kctl) {
2697978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2698978e77e7STakashi Iwai 			return true;
2699978e77e7STakashi Iwai 	}
2700978e77e7STakashi Iwai 	return false;
2701978e77e7STakashi Iwai }
2702978e77e7STakashi Iwai 
2703978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2704978e77e7STakashi Iwai 			       char *name, size_t name_len)
2705978e77e7STakashi Iwai {
2706978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2707978e77e7STakashi Iwai 	int idx = 0;
2708978e77e7STakashi Iwai 
2709978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2710978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2711978e77e7STakashi Iwai 
2712978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2713978e77e7STakashi Iwai 		;
2714978e77e7STakashi Iwai }
2715978e77e7STakashi Iwai 
27165f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
27175f171baaSTakashi Iwai {
27185f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2719f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
27205f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
27215f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
27225f171baaSTakashi Iwai 			return 2;
27235f171baaSTakashi Iwai 	}
27245f171baaSTakashi Iwai 	return 1;
27255f171baaSTakashi Iwai }
27265f171baaSTakashi Iwai 
2727978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2728978e77e7STakashi Iwai 				 hda_nid_t *pins)
2729978e77e7STakashi Iwai {
2730978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2731978e77e7STakashi Iwai 	int i;
2732978e77e7STakashi Iwai 
2733978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2734978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2735ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
27365f171baaSTakashi Iwai 			continue;
27375f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2738978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2739975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2740978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2741978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2742978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2743978e77e7STakashi Iwai 			if (!knew)
2744978e77e7STakashi Iwai 				return -ENOMEM;
2745978e77e7STakashi Iwai 			knew->private_value = pin;
2746978e77e7STakashi Iwai 		}
2747978e77e7STakashi Iwai 	}
2748978e77e7STakashi Iwai 
2749978e77e7STakashi Iwai 	return 0;
2750978e77e7STakashi Iwai }
2751978e77e7STakashi Iwai 
275229476558STakashi Iwai /*
275329476558STakashi Iwai  * input jack mode
275429476558STakashi Iwai  */
275529476558STakashi Iwai 
275629476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
275729476558STakashi Iwai #define NUM_VREFS	6
275829476558STakashi Iwai 
275929476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
276029476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
276129476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
276229476558STakashi Iwai };
276329476558STakashi Iwai 
276429476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
276529476558STakashi Iwai {
276629476558STakashi Iwai 	unsigned int pincap;
276729476558STakashi Iwai 
276829476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
276929476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
277029476558STakashi Iwai 	/* filter out unusual vrefs */
277129476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
277229476558STakashi Iwai 	return pincap;
277329476558STakashi Iwai }
277429476558STakashi Iwai 
277529476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
277629476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
277729476558STakashi Iwai {
277829476558STakashi Iwai 	unsigned int i, n = 0;
277929476558STakashi Iwai 
278029476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
278129476558STakashi Iwai 		if (vref_caps & (1 << i)) {
278229476558STakashi Iwai 			if (n == item_idx)
278329476558STakashi Iwai 				return i;
278429476558STakashi Iwai 			n++;
278529476558STakashi Iwai 		}
278629476558STakashi Iwai 	}
278729476558STakashi Iwai 	return 0;
278829476558STakashi Iwai }
278929476558STakashi Iwai 
279029476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
279129476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
279229476558STakashi Iwai {
279329476558STakashi Iwai 	unsigned int i, n = 0;
279429476558STakashi Iwai 
279529476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
279629476558STakashi Iwai 		if (i == idx)
279729476558STakashi Iwai 			return n;
279829476558STakashi Iwai 		if (vref_caps & (1 << i))
279929476558STakashi Iwai 			n++;
280029476558STakashi Iwai 	}
280129476558STakashi Iwai 	return 0;
280229476558STakashi Iwai }
280329476558STakashi Iwai 
280429476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
280529476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
280629476558STakashi Iwai {
280729476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
280829476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
280929476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
281029476558STakashi Iwai 
281129476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
281229476558STakashi Iwai 				 vref_texts);
281329476558STakashi Iwai 	/* set the right text */
281429476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
281529476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
281629476558STakashi Iwai 	return 0;
281729476558STakashi Iwai }
281829476558STakashi Iwai 
281929476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
282029476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
282129476558STakashi Iwai {
282229476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
282329476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
282429476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
282529476558STakashi Iwai 	unsigned int idx;
282629476558STakashi Iwai 
282729476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
282829476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
282929476558STakashi Iwai 	return 0;
283029476558STakashi Iwai }
283129476558STakashi Iwai 
283229476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
283329476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
283429476558STakashi Iwai {
283529476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
283629476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
283729476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
283829476558STakashi Iwai 	unsigned int val, idx;
283929476558STakashi Iwai 
284029476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
284129476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
284229476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
284329476558STakashi Iwai 		return 0;
284429476558STakashi Iwai 
284529476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
284629476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
284729476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
284829476558STakashi Iwai 	return 1;
284929476558STakashi Iwai }
285029476558STakashi Iwai 
285129476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
285229476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
285329476558STakashi Iwai 	.info = in_jack_mode_info,
285429476558STakashi Iwai 	.get = in_jack_mode_get,
285529476558STakashi Iwai 	.put = in_jack_mode_put,
285629476558STakashi Iwai };
285729476558STakashi Iwai 
28585f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
28595f171baaSTakashi Iwai {
28605f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28615f171baaSTakashi Iwai 	int nitems = 0;
2862f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
28635f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
28645f171baaSTakashi Iwai 	return nitems ? nitems : 1;
28655f171baaSTakashi Iwai }
28665f171baaSTakashi Iwai 
286729476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
286829476558STakashi Iwai {
286929476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
287029476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2871975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
28725f171baaSTakashi Iwai 	unsigned int defcfg;
28735f171baaSTakashi Iwai 
2874f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2875f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
287629476558STakashi Iwai 
287729476558STakashi Iwai 	/* no jack mode for fixed pins */
287829476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
287929476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
288029476558STakashi Iwai 		return 0;
288129476558STakashi Iwai 
288229476558STakashi Iwai 	/* no multiple vref caps? */
28835f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
288429476558STakashi Iwai 		return 0;
288529476558STakashi Iwai 
288629476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
288729476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
288829476558STakashi Iwai 	if (!knew)
288929476558STakashi Iwai 		return -ENOMEM;
289029476558STakashi Iwai 	knew->private_value = pin;
289129476558STakashi Iwai 	return 0;
289229476558STakashi Iwai }
289329476558STakashi Iwai 
28945f171baaSTakashi Iwai /*
28955f171baaSTakashi Iwai  * HP/mic shared jack mode
28965f171baaSTakashi Iwai  */
28975f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
28985f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
28995f171baaSTakashi Iwai {
29005f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29015f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29025f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29035f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29045f171baaSTakashi Iwai 	const char *text = NULL;
29055f171baaSTakashi Iwai 	int idx;
29065f171baaSTakashi Iwai 
29075f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
29085f171baaSTakashi Iwai 	uinfo->count = 1;
29095f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
29105f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
29115f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
29125f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
29135f171baaSTakashi Iwai 	if (idx < out_jacks) {
29145f171baaSTakashi Iwai 		if (out_jacks > 1)
29155f171baaSTakashi Iwai 			text = out_jack_texts[idx];
29165f171baaSTakashi Iwai 		else
29175f171baaSTakashi Iwai 			text = "Headphone Out";
29185f171baaSTakashi Iwai 	} else {
29195f171baaSTakashi Iwai 		idx -= out_jacks;
29205f171baaSTakashi Iwai 		if (in_jacks > 1) {
29215f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29225f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
29235f171baaSTakashi Iwai 		} else
29245f171baaSTakashi Iwai 			text = "Mic In";
29255f171baaSTakashi Iwai 	}
29265f171baaSTakashi Iwai 
29275f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
29285f171baaSTakashi Iwai 	return 0;
29295f171baaSTakashi Iwai }
29305f171baaSTakashi Iwai 
29315f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
29325f171baaSTakashi Iwai {
29335f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29345f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29355f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
29365f171baaSTakashi Iwai 	int idx = 0;
29375f171baaSTakashi Iwai 
29385f171baaSTakashi Iwai 	if (val & PIN_OUT) {
29395f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
29405f171baaSTakashi Iwai 			idx = 1;
29415f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
29425f171baaSTakashi Iwai 		idx = out_jacks;
29435f171baaSTakashi Iwai 		if (in_jacks > 1) {
29445f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29455f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
29465f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
29475f171baaSTakashi Iwai 		}
29485f171baaSTakashi Iwai 	}
29495f171baaSTakashi Iwai 	return idx;
29505f171baaSTakashi Iwai }
29515f171baaSTakashi Iwai 
29525f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
29535f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29545f171baaSTakashi Iwai {
29555f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29565f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29575f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
29585f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
29595f171baaSTakashi Iwai 	return 0;
29605f171baaSTakashi Iwai }
29615f171baaSTakashi Iwai 
29625f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
29635f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29645f171baaSTakashi Iwai {
29655f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29665f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29675f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29685f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29695f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
29705f171baaSTakashi Iwai 
29715f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
29725f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
29735f171baaSTakashi Iwai 	if (oldval == idx)
29745f171baaSTakashi Iwai 		return 0;
29755f171baaSTakashi Iwai 
29765f171baaSTakashi Iwai 	if (idx < out_jacks) {
29775f171baaSTakashi Iwai 		if (out_jacks > 1)
29785f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
29795f171baaSTakashi Iwai 		else
29805f171baaSTakashi Iwai 			val = PIN_HP;
29815f171baaSTakashi Iwai 	} else {
29825f171baaSTakashi Iwai 		idx -= out_jacks;
29835f171baaSTakashi Iwai 		if (in_jacks > 1) {
29845f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29855f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
29863f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
29873f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
29885f171baaSTakashi Iwai 		} else
298916c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
29905f171baaSTakashi Iwai 	}
29915f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2992963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
29938ba955ceSTakashi Iwai 
29945f171baaSTakashi Iwai 	return 1;
29955f171baaSTakashi Iwai }
29965f171baaSTakashi Iwai 
29975f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
29985f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
29995f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
30005f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
30015f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
30025f171baaSTakashi Iwai };
30035f171baaSTakashi Iwai 
30045f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
30055f171baaSTakashi Iwai {
30065f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
30075f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
30085f171baaSTakashi Iwai 
30095f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
30105f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
30115f171baaSTakashi Iwai 	if (!knew)
30125f171baaSTakashi Iwai 		return -ENOMEM;
30135f171baaSTakashi Iwai 	knew->private_value = pin;
30148ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
30155f171baaSTakashi Iwai 	return 0;
30165f171baaSTakashi Iwai }
3017352f7f91STakashi Iwai 
3018352f7f91STakashi Iwai /*
3019352f7f91STakashi Iwai  * Parse input paths
3020352f7f91STakashi Iwai  */
3021352f7f91STakashi Iwai 
3022352f7f91STakashi Iwai /* add the powersave loopback-list entry */
30230186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
3024352f7f91STakashi Iwai {
3025352f7f91STakashi Iwai 	struct hda_amp_list *list;
3026352f7f91STakashi Iwai 
30270186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
30280186f4f4STakashi Iwai 	if (!list)
30290186f4f4STakashi Iwai 		return -ENOMEM;
3030352f7f91STakashi Iwai 	list->nid = mix;
3031352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
3032352f7f91STakashi Iwai 	list->idx = idx;
30330186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
30340186f4f4STakashi Iwai 	return 0;
3035cb53c626STakashi Iwai }
3036cb53c626STakashi Iwai 
30372ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
30382ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
30392ded3e5bSTakashi Iwai  */
30402ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
30412ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
30422ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
30432ded3e5bSTakashi Iwai {
30442ded3e5bSTakashi Iwai 	int idx, num_conns;
30452ded3e5bSTakashi Iwai 	const hda_nid_t *list;
30462ded3e5bSTakashi Iwai 	hda_nid_t nid;
30472ded3e5bSTakashi Iwai 
30482ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
30492ded3e5bSTakashi Iwai 	if (idx < 0)
30502ded3e5bSTakashi Iwai 		return false;
30512ded3e5bSTakashi Iwai 
30522ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
30532ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
30542ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30552ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
30562ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30572ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
30582ded3e5bSTakashi Iwai 		return true;
30592ded3e5bSTakashi Iwai 
30602ded3e5bSTakashi Iwai 	/* check leaf node */
30612ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
30622ded3e5bSTakashi Iwai 	if (num_conns < idx)
30632ded3e5bSTakashi Iwai 		return false;
30642ded3e5bSTakashi Iwai 	nid = list[idx];
306543a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
306643a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
30672ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
306843a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
306943a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
30702ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
30712ded3e5bSTakashi Iwai 
30722ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
30732ded3e5bSTakashi Iwai }
30742ded3e5bSTakashi Iwai 
3075352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
3076196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
3077196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3078352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
30791da177e4SLinus Torvalds {
3080352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3081352f7f91STakashi Iwai 	struct nid_path *path;
30822ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
3083352f7f91STakashi Iwai 	int err, idx;
30841da177e4SLinus Torvalds 
30852ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
30862ded3e5bSTakashi Iwai 		return 0;
3087352f7f91STakashi Iwai 
30883ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3089352f7f91STakashi Iwai 	if (!path)
3090352f7f91STakashi Iwai 		return -EINVAL;
30914e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
3092196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3093352f7f91STakashi Iwai 
3094352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
30952ded3e5bSTakashi Iwai 	if (mix_val) {
30962ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3097d13bd412STakashi Iwai 		if (err < 0)
30981da177e4SLinus Torvalds 			return err;
30992ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
31001da177e4SLinus Torvalds 	}
31011da177e4SLinus Torvalds 
31022ded3e5bSTakashi Iwai 	if (mute_val) {
31032ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3104d13bd412STakashi Iwai 		if (err < 0)
31051da177e4SLinus Torvalds 			return err;
31062ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
31071da177e4SLinus Torvalds 	}
31081da177e4SLinus Torvalds 
3109352f7f91STakashi Iwai 	path->active = true;
3110e6feb5d0STakashi Iwai 	path->stream_enabled = true; /* no DAC/ADC involved */
31110186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
31120186f4f4STakashi Iwai 	if (err < 0)
31130186f4f4STakashi Iwai 		return err;
3114e4a395e7STakashi Iwai 
3115e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3116e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
3117e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3118e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
3119e4a395e7STakashi Iwai 		if (path) {
31204e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
3121e4a395e7STakashi Iwai 			path->active = true;
31226b275b14STakashi Iwai 			path->pin_fixed = true; /* static route */
3123e6feb5d0STakashi Iwai 			path->stream_enabled = true; /* no DAC/ADC involved */
3124e4a395e7STakashi Iwai 			spec->loopback_merge_path =
3125e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
3126e4a395e7STakashi Iwai 		}
3127e4a395e7STakashi Iwai 	}
3128e4a395e7STakashi Iwai 
3129352f7f91STakashi Iwai 	return 0;
31301da177e4SLinus Torvalds }
31311da177e4SLinus Torvalds 
3132352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
31331da177e4SLinus Torvalds {
3134352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3135352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
3136352f7f91STakashi Iwai }
3137352f7f91STakashi Iwai 
3138352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
3139352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
3140352f7f91STakashi Iwai {
3141352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3142352f7f91STakashi Iwai 	hda_nid_t nid;
3143352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
3144352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
31457639a06cSTakashi Iwai 	int nums = 0;
3146352f7f91STakashi Iwai 
31477639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
3148352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3149352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3150352f7f91STakashi Iwai 
3151352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3152352f7f91STakashi Iwai 			continue;
3153352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3154352f7f91STakashi Iwai 		if (++nums >= max_nums)
3155352f7f91STakashi Iwai 			break;
3156352f7f91STakashi Iwai 	}
3157352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
31580ffd534eSTakashi Iwai 
31590ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
31600ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
31610ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
31620ffd534eSTakashi Iwai 
3163352f7f91STakashi Iwai 	return nums;
3164352f7f91STakashi Iwai }
3165352f7f91STakashi Iwai 
3166352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3167352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3168352f7f91STakashi Iwai  */
3169352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3170352f7f91STakashi Iwai {
3171352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3172352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
31733a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3174352f7f91STakashi Iwai 	int i, n, nums;
3175352f7f91STakashi Iwai 
3176352f7f91STakashi Iwai 	nums = 0;
31773a65bcdcSTakashi Iwai 	ok_bits = 0;
3178352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3179352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
31803a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3181352f7f91STakashi Iwai 				break;
3182352f7f91STakashi Iwai 		}
31833a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
31843a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
31853a65bcdcSTakashi Iwai 			nums++;
31863a65bcdcSTakashi Iwai 		}
3187352f7f91STakashi Iwai 	}
3188352f7f91STakashi Iwai 
31893a65bcdcSTakashi Iwai 	if (!ok_bits) {
3190352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3191352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3192352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
31933a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3194352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3195352f7f91STakashi Iwai 					break;
3196352f7f91STakashi Iwai 				}
3197352f7f91STakashi Iwai 			}
3198352f7f91STakashi Iwai 		}
3199352f7f91STakashi Iwai 
32004e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3201352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3202352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
32033a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
32043a65bcdcSTakashi Iwai 		nums = 0;
32053a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
32063a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
32073a65bcdcSTakashi Iwai 				continue;
32083a65bcdcSTakashi Iwai 			if (n != nums) {
32093a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3210980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3211980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3212980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
32133a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
32143a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
3215a8f20fd2SHui Wang 					spec->input_paths[i][n] = 0;
32163a65bcdcSTakashi Iwai 				}
3217980428ceSTakashi Iwai 			}
32183a65bcdcSTakashi Iwai 			nums++;
32193a65bcdcSTakashi Iwai 		}
3220352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3221352f7f91STakashi Iwai 	}
3222352f7f91STakashi Iwai 
3223967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3224967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
32254e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3226352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3227352f7f91STakashi Iwai 	}
3228352f7f91STakashi Iwai 
3229352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3230352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3231352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3232352f7f91STakashi Iwai 
32331da177e4SLinus Torvalds 	return 0;
32341da177e4SLinus Torvalds }
32351da177e4SLinus Torvalds 
3236f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3237f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
32389dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
32399dba205bSTakashi Iwai 				const char *label, int anchor)
3240f3fc0b0bSTakashi Iwai {
3241f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3242f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3243f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3244f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3245f3fc0b0bSTakashi Iwai 	int c;
3246f3fc0b0bSTakashi Iwai 
3247f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3248f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3249f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3250f3fc0b0bSTakashi Iwai 
3251f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3252f3fc0b0bSTakashi Iwai 			continue;
3253f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3254f3fc0b0bSTakashi Iwai 		if (!path)
3255f3fc0b0bSTakashi Iwai 			continue;
32564e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3257f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3258f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3259f3fc0b0bSTakashi Iwai 
3260f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3261967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3262967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3263f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
32646194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3265f3fc0b0bSTakashi Iwai 			imux_added = true;
3266f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3267f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3268f3fc0b0bSTakashi Iwai 		}
3269f3fc0b0bSTakashi Iwai 	}
3270f3fc0b0bSTakashi Iwai 
3271f3fc0b0bSTakashi Iwai 	return 0;
3272f3fc0b0bSTakashi Iwai }
3273f3fc0b0bSTakashi Iwai 
32741da177e4SLinus Torvalds /*
3275352f7f91STakashi Iwai  * create playback/capture controls for input pins
32761da177e4SLinus Torvalds  */
32779dba205bSTakashi Iwai 
3278c970042cSTakashi Iwai /* fill the label for each input at first */
3279c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3280c970042cSTakashi Iwai {
3281c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3282c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3283c970042cSTakashi Iwai 	int i;
3284c970042cSTakashi Iwai 
3285c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3286c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3287c970042cSTakashi Iwai 		const char *label;
3288c970042cSTakashi Iwai 		int j, idx;
3289c970042cSTakashi Iwai 
3290c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3291c970042cSTakashi Iwai 			continue;
3292c970042cSTakashi Iwai 
3293c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3294c970042cSTakashi Iwai 		idx = 0;
32958e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3296c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3297c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3298c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3299c970042cSTakashi Iwai 				break;
3300c970042cSTakashi Iwai 			}
3301c970042cSTakashi Iwai 		}
3302c970042cSTakashi Iwai 
3303c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3304c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3305c970042cSTakashi Iwai 	}
3306c970042cSTakashi Iwai 
3307c970042cSTakashi Iwai 	return 0;
3308c970042cSTakashi Iwai }
3309c970042cSTakashi Iwai 
33109dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
33119dba205bSTakashi Iwai 
3312352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3313a7da6ce5STakashi Iwai {
3314352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3315352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3316352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3317352f7f91STakashi Iwai 	int num_adcs;
3318c970042cSTakashi Iwai 	int i, err;
33192c12c30dSTakashi Iwai 	unsigned int val;
3320a7da6ce5STakashi Iwai 
3321352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3322352f7f91STakashi Iwai 	if (num_adcs < 0)
3323352f7f91STakashi Iwai 		return 0;
3324352f7f91STakashi Iwai 
3325c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3326c970042cSTakashi Iwai 	if (err < 0)
3327c970042cSTakashi Iwai 		return err;
3328c970042cSTakashi Iwai 
3329352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3330352f7f91STakashi Iwai 		hda_nid_t pin;
3331352f7f91STakashi Iwai 
3332352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3333352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3334352f7f91STakashi Iwai 			continue;
3335352f7f91STakashi Iwai 
33362c12c30dSTakashi Iwai 		val = PIN_IN;
33372c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
33382c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
33393e1b0c4aSTakashi Iwai 		if (pin != spec->hp_mic_pin &&
33403e1b0c4aSTakashi Iwai 		    !snd_hda_codec_get_pin_target(codec, pin))
33412c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
33422c12c30dSTakashi Iwai 
3343352f7f91STakashi Iwai 		if (mixer) {
3344352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3345196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3346c970042cSTakashi Iwai 						       spec->input_labels[i],
3347c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3348c970042cSTakashi Iwai 						       mixer);
3349a7da6ce5STakashi Iwai 				if (err < 0)
3350a7da6ce5STakashi Iwai 					return err;
3351a7da6ce5STakashi Iwai 			}
3352352f7f91STakashi Iwai 		}
3353352f7f91STakashi Iwai 
3354c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3355c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3356f3fc0b0bSTakashi Iwai 		if (err < 0)
3357f3fc0b0bSTakashi Iwai 			return err;
335829476558STakashi Iwai 
3359f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
336029476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
336129476558STakashi Iwai 			if (err < 0)
336229476558STakashi Iwai 				return err;
336329476558STakashi Iwai 		}
3364352f7f91STakashi Iwai 	}
3365f3fc0b0bSTakashi Iwai 
3366f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
336774f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
33689dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3369f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3370f3fc0b0bSTakashi Iwai 		if (err < 0)
3371f3fc0b0bSTakashi Iwai 			return err;
337282d04e10STakashi Iwai 		else
337382d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3374352f7f91STakashi Iwai 	}
3375352f7f91STakashi Iwai 
3376a7da6ce5STakashi Iwai 	return 0;
3377a7da6ce5STakashi Iwai }
3378a7da6ce5STakashi Iwai 
33791da177e4SLinus Torvalds 
3380352f7f91STakashi Iwai /*
3381352f7f91STakashi Iwai  * input source mux
3382352f7f91STakashi Iwai  */
3383352f7f91STakashi Iwai 
3384c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3385c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3386352f7f91STakashi Iwai {
3387352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3388b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3389b56fa1edSDavid Henningsson 		snd_BUG();
3390b56fa1edSDavid Henningsson 		return NULL;
3391b56fa1edSDavid Henningsson 	}
3392352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3393352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3394d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3395b56fa1edSDavid Henningsson 		snd_BUG();
3396b56fa1edSDavid Henningsson 		return NULL;
3397b56fa1edSDavid Henningsson 	}
3398c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
339997ec558aSTakashi Iwai }
3400352f7f91STakashi Iwai 
3401352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3402352f7f91STakashi Iwai 		      unsigned int idx);
3403352f7f91STakashi Iwai 
3404352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3405352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3406352f7f91STakashi Iwai {
3407352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3408352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3409352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3410352f7f91STakashi Iwai }
3411352f7f91STakashi Iwai 
3412352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3413352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3414352f7f91STakashi Iwai {
3415352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3416352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
34172a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
34182a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3419352f7f91STakashi Iwai 
3420352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
34211da177e4SLinus Torvalds 	return 0;
34221da177e4SLinus Torvalds }
34231da177e4SLinus Torvalds 
3424352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3425352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
34261da177e4SLinus Torvalds {
3427352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34282a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3429352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3430352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3431352f7f91STakashi Iwai }
3432352f7f91STakashi Iwai 
3433352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
34341da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3435352f7f91STakashi Iwai 	.name = "Input Source",
3436352f7f91STakashi Iwai 	.info = mux_enum_info,
3437352f7f91STakashi Iwai 	.get = mux_enum_get,
3438352f7f91STakashi Iwai 	.put = mux_enum_put,
34391da177e4SLinus Torvalds };
3440071c73adSTakashi Iwai 
344147d46abbSTakashi Iwai /*
344247d46abbSTakashi Iwai  * capture volume and capture switch ctls
344347d46abbSTakashi Iwai  */
344447d46abbSTakashi Iwai 
3445352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3446352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3447071c73adSTakashi Iwai 
344847d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3449352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3450352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3451352f7f91STakashi Iwai 			  put_call_t func, int type)
3452352f7f91STakashi Iwai {
3453352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3454352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3455352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3456352f7f91STakashi Iwai 	struct nid_path *path;
3457352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3458071c73adSTakashi Iwai 
3459352f7f91STakashi Iwai 	imux = &spec->input_mux;
3460a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3461352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
3462352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3463c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3464c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3465352f7f91STakashi Iwai 			continue;
3466352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3467352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3468352f7f91STakashi Iwai 		if (err < 0)
3469a551d914STakashi Iwai 			break;
3470352f7f91STakashi Iwai 	}
3471352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3472352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
34737fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3474352f7f91STakashi Iwai 	return err;
3475352f7f91STakashi Iwai }
3476352f7f91STakashi Iwai 
3477352f7f91STakashi Iwai /* capture volume ctl callbacks */
3478352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3479352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3480352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3481352f7f91STakashi Iwai 
3482352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3483352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3484352f7f91STakashi Iwai {
3485352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3486352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3487352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3488352f7f91STakashi Iwai }
3489352f7f91STakashi Iwai 
3490352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3491352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3492352f7f91STakashi Iwai 	.name = "Capture Volume",
3493352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3494352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3495352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3496352f7f91STakashi Iwai 	.info = cap_vol_info,
3497352f7f91STakashi Iwai 	.get = cap_vol_get,
3498352f7f91STakashi Iwai 	.put = cap_vol_put,
3499352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3500352f7f91STakashi Iwai };
3501352f7f91STakashi Iwai 
3502352f7f91STakashi Iwai /* capture switch ctl callbacks */
3503352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3504352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3505352f7f91STakashi Iwai 
3506352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3507352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3508352f7f91STakashi Iwai {
3509a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3510352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3511352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3512352f7f91STakashi Iwai }
3513352f7f91STakashi Iwai 
3514352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3515352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3516352f7f91STakashi Iwai 	.name = "Capture Switch",
3517352f7f91STakashi Iwai 	.info = cap_sw_info,
3518352f7f91STakashi Iwai 	.get = cap_sw_get,
3519352f7f91STakashi Iwai 	.put = cap_sw_put,
3520352f7f91STakashi Iwai };
3521352f7f91STakashi Iwai 
3522352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3523352f7f91STakashi Iwai {
3524352f7f91STakashi Iwai 	hda_nid_t nid;
3525352f7f91STakashi Iwai 	int i, depth;
3526352f7f91STakashi Iwai 
3527352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3528352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3529352f7f91STakashi Iwai 		if (depth >= path->depth)
3530352f7f91STakashi Iwai 			return -EINVAL;
3531352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3532352f7f91STakashi Iwai 		nid = path->path[i];
3533352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3534352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3535352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3536352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3537352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3538352f7f91STakashi Iwai 				int idx = path->idx[i];
3539352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3540352f7f91STakashi Iwai 					idx = 0;
3541352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3542352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3543352f7f91STakashi Iwai 			}
3544352f7f91STakashi Iwai 		}
3545352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3546352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3547352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3548352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3549352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3550352f7f91STakashi Iwai 				int idx = path->idx[i];
3551352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3552352f7f91STakashi Iwai 					idx = 0;
3553352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3554352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3555352f7f91STakashi Iwai 			}
3556352f7f91STakashi Iwai 		}
3557352f7f91STakashi Iwai 	}
3558352f7f91STakashi Iwai 	return 0;
3559352f7f91STakashi Iwai }
3560352f7f91STakashi Iwai 
3561352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3562352f7f91STakashi Iwai {
3563352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3564352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3565352f7f91STakashi Iwai 	unsigned int val;
3566352f7f91STakashi Iwai 	int i;
3567352f7f91STakashi Iwai 
3568352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3569352f7f91STakashi Iwai 		return false;
3570352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3571352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3572352f7f91STakashi Iwai 			continue;
3573352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3574352f7f91STakashi Iwai 			return false;
3575352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3576352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3577352f7f91STakashi Iwai 	}
3578352f7f91STakashi Iwai 	return false;
3579352f7f91STakashi Iwai }
3580352f7f91STakashi Iwai 
3581a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3582a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3583a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3584a35bd1e3STakashi Iwai {
3585a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3586a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3587a35bd1e3STakashi Iwai 	int ret;
3588a35bd1e3STakashi Iwai 
3589a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3590a35bd1e3STakashi Iwai 	if (ret < 0)
3591a35bd1e3STakashi Iwai 		return ret;
3592a35bd1e3STakashi Iwai 
3593a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
35947fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3595a35bd1e3STakashi Iwai 
3596a35bd1e3STakashi Iwai 	return ret;
3597a35bd1e3STakashi Iwai }
3598a35bd1e3STakashi Iwai 
3599352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3600352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3601352f7f91STakashi Iwai 			      bool inv_dmic)
3602352f7f91STakashi Iwai {
3603352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3604975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3605352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3606352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3607352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3608a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3609352f7f91STakashi Iwai 
3610352f7f91STakashi Iwai 	if (!ctl)
3611352f7f91STakashi Iwai 		return 0;
3612352f7f91STakashi Iwai 
3613352f7f91STakashi Iwai 	if (label)
3614352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3615352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3616352f7f91STakashi Iwai 	else
3617352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3618352f7f91STakashi Iwai 			 "Capture %s", sfx);
3619a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3620352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3621a35bd1e3STakashi Iwai 	if (!knew)
3622a35bd1e3STakashi Iwai 		return -ENOMEM;
3623*e65bf997SJaroslav Kysela 	if (is_switch) {
3624a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3625*e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3626*e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3627*e65bf997SJaroslav Kysela 	}
3628a35bd1e3STakashi Iwai 	if (!inv_dmic)
3629a35bd1e3STakashi Iwai 		return 0;
3630352f7f91STakashi Iwai 
3631352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3632352f7f91STakashi Iwai 	if (label)
3633352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3634352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3635352f7f91STakashi Iwai 	else
3636352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3637352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3638a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3639352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3640a35bd1e3STakashi Iwai 	if (!knew)
3641a35bd1e3STakashi Iwai 		return -ENOMEM;
3642*e65bf997SJaroslav Kysela 	if (is_switch) {
3643a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3644*e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3645*e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3646*e65bf997SJaroslav Kysela 	}
3647a35bd1e3STakashi Iwai 	return 0;
3648352f7f91STakashi Iwai }
3649352f7f91STakashi Iwai 
3650352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3651352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3652352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3653352f7f91STakashi Iwai 				     bool inv_dmic)
3654352f7f91STakashi Iwai {
3655352f7f91STakashi Iwai 	int err;
3656352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3657352f7f91STakashi Iwai 	if (err < 0)
3658352f7f91STakashi Iwai 		return err;
3659352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3660071c73adSTakashi Iwai 	if (err < 0)
3661071c73adSTakashi Iwai 		return err;
3662071c73adSTakashi Iwai 	return 0;
36631da177e4SLinus Torvalds }
3664071c73adSTakashi Iwai 
3665352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3666352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3667352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3668352f7f91STakashi Iwai {
3669352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3670352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3671352f7f91STakashi Iwai 
3672352f7f91STakashi Iwai 	if (vol_ctl) {
367312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3674352f7f91STakashi Iwai 		if (!knew)
3675352f7f91STakashi Iwai 			return -ENOMEM;
3676352f7f91STakashi Iwai 		knew->index = idx;
3677352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3678352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3679352f7f91STakashi Iwai 	}
3680352f7f91STakashi Iwai 	if (sw_ctl) {
368112c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3682352f7f91STakashi Iwai 		if (!knew)
3683352f7f91STakashi Iwai 			return -ENOMEM;
3684352f7f91STakashi Iwai 		knew->index = idx;
3685352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3686352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3687*e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3688*e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3689352f7f91STakashi Iwai 	}
3690352f7f91STakashi Iwai 	return 0;
3691352f7f91STakashi Iwai }
3692352f7f91STakashi Iwai 
3693352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3694352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3695352f7f91STakashi Iwai {
3696352f7f91STakashi Iwai 	struct nid_path *path;
3697352f7f91STakashi Iwai 	unsigned int ctl;
3698352f7f91STakashi Iwai 	int i;
3699352f7f91STakashi Iwai 
3700c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3701352f7f91STakashi Iwai 	if (!path)
3702352f7f91STakashi Iwai 		return 0;
3703352f7f91STakashi Iwai 	ctl = path->ctls[type];
3704352f7f91STakashi Iwai 	if (!ctl)
3705352f7f91STakashi Iwai 		return 0;
3706352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3707c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3708352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3709352f7f91STakashi Iwai 			return 0;
3710352f7f91STakashi Iwai 	}
3711352f7f91STakashi Iwai 	return ctl;
3712352f7f91STakashi Iwai }
3713352f7f91STakashi Iwai 
3714352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3715352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3716352f7f91STakashi Iwai {
3717352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3718352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3719c970042cSTakashi Iwai 	int i, err, type;
3720352f7f91STakashi Iwai 
3721352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3722352f7f91STakashi Iwai 		bool inv_dmic;
3723c970042cSTakashi Iwai 		int idx;
37249dba205bSTakashi Iwai 
3725c970042cSTakashi Iwai 		idx = imux->items[i].index;
3726c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
37279dba205bSTakashi Iwai 			continue;
3728352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3729352f7f91STakashi Iwai 
3730352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3731c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3732c970042cSTakashi Iwai 						 spec->input_labels[idx],
3733c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3734c970042cSTakashi Iwai 						 type,
3735352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3736352f7f91STakashi Iwai 						 inv_dmic);
3737d13bd412STakashi Iwai 			if (err < 0)
3738071c73adSTakashi Iwai 				return err;
3739352f7f91STakashi Iwai 		}
3740352f7f91STakashi Iwai 	}
3741071c73adSTakashi Iwai 	return 0;
3742352f7f91STakashi Iwai }
3743071c73adSTakashi Iwai 
3744352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3745352f7f91STakashi Iwai {
3746352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3747352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3748352f7f91STakashi Iwai 	int i, n, nums, err;
3749352f7f91STakashi Iwai 
3750352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3751352f7f91STakashi Iwai 		nums = 1;
3752352f7f91STakashi Iwai 	else
3753352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3754352f7f91STakashi Iwai 
3755352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3756352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3757624d914dSTakashi Iwai 		const char *name;
3758624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3759624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3760352f7f91STakashi Iwai 		if (!knew)
3761352f7f91STakashi Iwai 			return -ENOMEM;
3762352f7f91STakashi Iwai 		knew->count = nums;
3763352f7f91STakashi Iwai 	}
3764352f7f91STakashi Iwai 
3765352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3766352f7f91STakashi Iwai 		bool multi = false;
376799a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3768352f7f91STakashi Iwai 		bool inv_dmic = false;
3769352f7f91STakashi Iwai 		int vol, sw;
3770352f7f91STakashi Iwai 
3771352f7f91STakashi Iwai 		vol = sw = 0;
3772352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3773352f7f91STakashi Iwai 			struct nid_path *path;
3774c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3775352f7f91STakashi Iwai 			if (!path)
3776352f7f91STakashi Iwai 				continue;
3777352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3778352f7f91STakashi Iwai 			if (!vol)
3779352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
378099a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3781352f7f91STakashi Iwai 				multi = true;
378299a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
378399a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
378499a5592dSDavid Henningsson 					multi_cap_vol = true;
378599a5592dSDavid Henningsson 			}
3786352f7f91STakashi Iwai 			if (!sw)
3787352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
378899a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3789352f7f91STakashi Iwai 				multi = true;
379099a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
379199a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
379299a5592dSDavid Henningsson 					multi_cap_vol = true;
379399a5592dSDavid Henningsson 			}
3794352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3795352f7f91STakashi Iwai 				inv_dmic = true;
3796352f7f91STakashi Iwai 		}
3797352f7f91STakashi Iwai 
3798352f7f91STakashi Iwai 		if (!multi)
3799352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3800352f7f91STakashi Iwai 							inv_dmic);
3801ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3802352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3803352f7f91STakashi Iwai 		else
3804352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3805d13bd412STakashi Iwai 		if (err < 0)
3806071c73adSTakashi Iwai 			return err;
3807071c73adSTakashi Iwai 	}
3808071c73adSTakashi Iwai 
38091da177e4SLinus Torvalds 	return 0;
38101da177e4SLinus Torvalds }
38111da177e4SLinus Torvalds 
3812352f7f91STakashi Iwai /*
3813352f7f91STakashi Iwai  * add mic boosts if needed
3814352f7f91STakashi Iwai  */
38156f7c83afSTakashi Iwai 
38166f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
38176f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
38186f7c83afSTakashi Iwai 			    int dir, int idx)
38196f7c83afSTakashi Iwai {
38206f7c83afSTakashi Iwai 	unsigned int step;
38216f7c83afSTakashi Iwai 
38226f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
38236f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
38246f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
38256f7c83afSTakashi Iwai 		return false;
38266f7c83afSTakashi Iwai 
38276f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
38286f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
38296f7c83afSTakashi Iwai 	if (step < 0x20)
38306f7c83afSTakashi Iwai 		return false;
38316f7c83afSTakashi Iwai 	return true;
38326f7c83afSTakashi Iwai }
38336f7c83afSTakashi Iwai 
38346f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
38356f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
38366f7c83afSTakashi Iwai 				       struct nid_path *path)
38376f7c83afSTakashi Iwai {
38386f7c83afSTakashi Iwai 	unsigned int val = 0;
38396f7c83afSTakashi Iwai 	hda_nid_t nid;
38406f7c83afSTakashi Iwai 	int depth;
38416f7c83afSTakashi Iwai 
38426f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
38436f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
38446f7c83afSTakashi Iwai 			break;
38456f7c83afSTakashi Iwai 		nid = path->path[depth];
38466f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
38476f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
38486f7c83afSTakashi Iwai 			break;
38496f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
38506f7c83afSTakashi Iwai 					   path->idx[depth])) {
38516f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
38526f7c83afSTakashi Iwai 						  HDA_INPUT);
38536f7c83afSTakashi Iwai 			break;
38546f7c83afSTakashi Iwai 		}
38556f7c83afSTakashi Iwai 	}
38566f7c83afSTakashi Iwai 
38576f7c83afSTakashi Iwai 	return val;
38586f7c83afSTakashi Iwai }
38596f7c83afSTakashi Iwai 
3860352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3861352f7f91STakashi Iwai {
3862352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3863352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
38646f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3865a35bd1e3STakashi Iwai 	int i;
3866352f7f91STakashi Iwai 
38676f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
38686f7c83afSTakashi Iwai 		return 0;
38696f7c83afSTakashi Iwai 
38706f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3871352f7f91STakashi Iwai 		struct nid_path *path;
3872352f7f91STakashi Iwai 		unsigned int val;
38736f7c83afSTakashi Iwai 		int idx;
3874975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3875352f7f91STakashi Iwai 
38766f7c83afSTakashi Iwai 		idx = imux->items[i].index;
38776f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
387802aba550SDavid Henningsson 			continue;
387902aba550SDavid Henningsson 
38806f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
38811799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
38826f7c83afSTakashi Iwai 			continue;
38836f7c83afSTakashi Iwai 
38846f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
38856f7c83afSTakashi Iwai 		if (!path)
38866f7c83afSTakashi Iwai 			continue;
38876f7c83afSTakashi Iwai 
38886f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
38896f7c83afSTakashi Iwai 		if (!val)
38906f7c83afSTakashi Iwai 			continue;
38916f7c83afSTakashi Iwai 
38926f7c83afSTakashi Iwai 		/* create a boost control */
3893352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
38946f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3895a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3896a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3897a35bd1e3STakashi Iwai 			return -ENOMEM;
3898352f7f91STakashi Iwai 
3899352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3900352f7f91STakashi Iwai 	}
3901352f7f91STakashi Iwai 	return 0;
3902352f7f91STakashi Iwai }
3903352f7f91STakashi Iwai 
39047cdf8c49STakashi Iwai #ifdef CONFIG_SND_HDA_GENERIC_LEDS
3905352f7f91STakashi Iwai /*
390615509b63STakashi Iwai  * vmaster mute LED hook helpers
390715509b63STakashi Iwai  */
390815509b63STakashi Iwai 
390915509b63STakashi Iwai static int create_mute_led_cdev(struct hda_codec *codec,
391015509b63STakashi Iwai 				int (*callback)(struct led_classdev *,
391115509b63STakashi Iwai 						enum led_brightness),
391215509b63STakashi Iwai 				bool micmute)
391315509b63STakashi Iwai {
391415509b63STakashi Iwai 	struct led_classdev *cdev;
391515509b63STakashi Iwai 
391615509b63STakashi Iwai 	cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
391715509b63STakashi Iwai 	if (!cdev)
391815509b63STakashi Iwai 		return -ENOMEM;
391915509b63STakashi Iwai 
392015509b63STakashi Iwai 	cdev->name = micmute ? "hda::micmute" : "hda::mute";
392115509b63STakashi Iwai 	cdev->max_brightness = 1;
392215509b63STakashi Iwai 	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
392315509b63STakashi Iwai 	cdev->brightness_set_blocking = callback;
392415509b63STakashi Iwai 	cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE);
3925c9e272f9STakashi Iwai 	cdev->flags = LED_CORE_SUSPENDRESUME;
392615509b63STakashi Iwai 
392715509b63STakashi Iwai 	return devm_led_classdev_register(&codec->core.dev, cdev);
392815509b63STakashi Iwai }
392915509b63STakashi Iwai 
393015509b63STakashi Iwai /**
39313531ba21SPierre-Louis Bossart  * snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
393215509b63STakashi Iwai  * @codec: the HDA codec
393315509b63STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
393415509b63STakashi Iwai  */
393515509b63STakashi Iwai int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
393615509b63STakashi Iwai 				  int (*callback)(struct led_classdev *,
393715509b63STakashi Iwai 						  enum led_brightness))
393815509b63STakashi Iwai {
393915509b63STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
394015509b63STakashi Iwai 	int err;
394115509b63STakashi Iwai 
394215509b63STakashi Iwai 	if (callback) {
394315509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, false);
394415509b63STakashi Iwai 		if (err) {
394515509b63STakashi Iwai 			codec_warn(codec, "failed to create a mute LED cdev\n");
394615509b63STakashi Iwai 			return err;
394715509b63STakashi Iwai 		}
394815509b63STakashi Iwai 	}
394915509b63STakashi Iwai 
395015509b63STakashi Iwai 	if (spec->vmaster_mute.hook)
395115509b63STakashi Iwai 		codec_err(codec, "vmaster hook already present before cdev!\n");
395215509b63STakashi Iwai 
3953*e65bf997SJaroslav Kysela 	spec->vmaster_mute_led = 1;
395415509b63STakashi Iwai 	return 0;
395515509b63STakashi Iwai }
395615509b63STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
395715509b63STakashi Iwai 
3958b3802783STakashi Iwai /**
39593531ba21SPierre-Louis Bossart  * snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
39607cdf8c49STakashi Iwai  * @codec: the HDA codec
39617cdf8c49STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
39627cdf8c49STakashi Iwai  *
39637cdf8c49STakashi Iwai  * Called from the codec drivers for offering the mic mute LED controls.
39647cdf8c49STakashi Iwai  * This creates a LED classdev and sets up the cap_sync_hook that is called at
39657cdf8c49STakashi Iwai  * each time when the capture mixer switch changes.
39667cdf8c49STakashi Iwai  *
39677cdf8c49STakashi Iwai  * When NULL is passed to @callback, no classdev is created but only the
39687cdf8c49STakashi Iwai  * LED-trigger is set up.
39697cdf8c49STakashi Iwai  *
39707cdf8c49STakashi Iwai  * Returns 0 or a negative error.
39717cdf8c49STakashi Iwai  */
39727cdf8c49STakashi Iwai int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
39737cdf8c49STakashi Iwai 				     int (*callback)(struct led_classdev *,
39747cdf8c49STakashi Iwai 						     enum led_brightness))
39757cdf8c49STakashi Iwai {
3976*e65bf997SJaroslav Kysela 	struct hda_gen_spec *spec = codec->spec;
39777cdf8c49STakashi Iwai 	int err;
39787cdf8c49STakashi Iwai 
39797cdf8c49STakashi Iwai 	if (callback) {
398015509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, true);
39817cdf8c49STakashi Iwai 		if (err) {
39827cdf8c49STakashi Iwai 			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
39837cdf8c49STakashi Iwai 			return err;
39847cdf8c49STakashi Iwai 		}
39857cdf8c49STakashi Iwai 	}
39867cdf8c49STakashi Iwai 
3987*e65bf997SJaroslav Kysela 	spec->mic_mute_led = 1;
3988*e65bf997SJaroslav Kysela 	return 0;
39897cdf8c49STakashi Iwai }
39907cdf8c49STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
39917cdf8c49STakashi Iwai #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
39927cdf8c49STakashi Iwai 
3993f567b788STakashi Iwai /*
3994352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
3995352f7f91STakashi Iwai  */
3996352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
3997352f7f91STakashi Iwai {
3998352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
39990c8c0f56STakashi Iwai 	struct nid_path *path;
4000352f7f91STakashi Iwai 	int i, nums;
40012c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
4002352f7f91STakashi Iwai 
40039ab0cb30STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a follower */
4004352f7f91STakashi Iwai 	nums = 0;
4005352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
40062c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
4007352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
4008352f7f91STakashi Iwai 		if (!dig_nid)
4009352f7f91STakashi Iwai 			continue;
40103ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
40110c8c0f56STakashi Iwai 		if (!path)
4012352f7f91STakashi Iwai 			continue;
40134e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
4014e1284af7STakashi Iwai 		path->active = true;
40156b275b14STakashi Iwai 		path->pin_fixed = true; /* no jack detection */
4016196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
40172c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
4018352f7f91STakashi Iwai 		if (!nums) {
4019352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
4020352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
4021352f7f91STakashi Iwai 		} else {
40229ab0cb30STakashi Iwai 			spec->multiout.follower_dig_outs = spec->follower_dig_outs;
40239ab0cb30STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1)
4024352f7f91STakashi Iwai 				break;
40259ab0cb30STakashi Iwai 			spec->follower_dig_outs[nums - 1] = dig_nid;
4026352f7f91STakashi Iwai 		}
4027352f7f91STakashi Iwai 		nums++;
4028352f7f91STakashi Iwai 	}
4029352f7f91STakashi Iwai 
4030352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
40312c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
40327639a06cSTakashi Iwai 		for_each_hda_codec_node(dig_nid, codec) {
4033352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
4034352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
4035352f7f91STakashi Iwai 				continue;
4036352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
4037352f7f91STakashi Iwai 				continue;
40382c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
4039352f7f91STakashi Iwai 			if (path) {
40404e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
4041352f7f91STakashi Iwai 				path->active = true;
40426b275b14STakashi Iwai 				path->pin_fixed = true; /* no jack */
4043352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
40442430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
40452c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
4046352f7f91STakashi Iwai 				break;
4047352f7f91STakashi Iwai 			}
4048352f7f91STakashi Iwai 		}
4049352f7f91STakashi Iwai 	}
4050352f7f91STakashi Iwai }
4051352f7f91STakashi Iwai 
40521da177e4SLinus Torvalds 
40531da177e4SLinus Torvalds /*
4054352f7f91STakashi Iwai  * input MUX handling
40551da177e4SLinus Torvalds  */
40561da177e4SLinus Torvalds 
4057352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
4058352f7f91STakashi Iwai 
4059352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
4060352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
4061352f7f91STakashi Iwai 		      unsigned int idx)
4062352f7f91STakashi Iwai {
4063352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4064352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
406555196fffSTakashi Iwai 	struct nid_path *old_path, *path;
4066352f7f91STakashi Iwai 
4067352f7f91STakashi Iwai 	imux = &spec->input_mux;
4068352f7f91STakashi Iwai 	if (!imux->num_items)
40691da177e4SLinus Torvalds 		return 0;
40701da177e4SLinus Torvalds 
4071352f7f91STakashi Iwai 	if (idx >= imux->num_items)
4072352f7f91STakashi Iwai 		idx = imux->num_items - 1;
4073352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
4074352f7f91STakashi Iwai 		return 0;
4075352f7f91STakashi Iwai 
407655196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
407755196fffSTakashi Iwai 	if (!old_path)
4078352f7f91STakashi Iwai 		return 0;
407955196fffSTakashi Iwai 	if (old_path->active)
408055196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
4081352f7f91STakashi Iwai 
4082352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
4083352f7f91STakashi Iwai 
4084967303daSTakashi Iwai 	if (spec->hp_mic)
4085967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
4086352f7f91STakashi Iwai 
4087352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4088352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
4089352f7f91STakashi Iwai 
4090c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
4091352f7f91STakashi Iwai 	if (!path)
4092352f7f91STakashi Iwai 		return 0;
4093352f7f91STakashi Iwai 	if (path->active)
4094352f7f91STakashi Iwai 		return 0;
4095352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
4096352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
40977fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
409855196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
40991da177e4SLinus Torvalds 	return 1;
41001da177e4SLinus Torvalds }
41011da177e4SLinus Torvalds 
4102e6feb5d0STakashi Iwai /* power up/down widgets in the all paths that match with the given NID
4103e6feb5d0STakashi Iwai  * as terminals (either start- or endpoint)
4104e6feb5d0STakashi Iwai  *
4105e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4106e6feb5d0STakashi Iwai  */
4107e6feb5d0STakashi Iwai static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
4108e6feb5d0STakashi Iwai 				int pin_state, int stream_state)
4109e6feb5d0STakashi Iwai {
4110e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4111e6feb5d0STakashi Iwai 	hda_nid_t last, changed = 0;
4112e6feb5d0STakashi Iwai 	struct nid_path *path;
4113e6feb5d0STakashi Iwai 	int n;
4114e6feb5d0STakashi Iwai 
4115a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, n, path) {
411681e43960SBob Copeland 		if (!path->depth)
411781e43960SBob Copeland 			continue;
4118e6feb5d0STakashi Iwai 		if (path->path[0] == nid ||
4119e6feb5d0STakashi Iwai 		    path->path[path->depth - 1] == nid) {
4120e6feb5d0STakashi Iwai 			bool pin_old = path->pin_enabled;
4121e6feb5d0STakashi Iwai 			bool stream_old = path->stream_enabled;
4122e6feb5d0STakashi Iwai 
4123e6feb5d0STakashi Iwai 			if (pin_state >= 0)
4124e6feb5d0STakashi Iwai 				path->pin_enabled = pin_state;
4125e6feb5d0STakashi Iwai 			if (stream_state >= 0)
4126e6feb5d0STakashi Iwai 				path->stream_enabled = stream_state;
41276b275b14STakashi Iwai 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
41286b275b14STakashi Iwai 			    || path->stream_enabled != stream_old) {
4129e6feb5d0STakashi Iwai 				last = path_power_update(codec, path, true);
4130e6feb5d0STakashi Iwai 				if (last)
4131e6feb5d0STakashi Iwai 					changed = last;
4132e6feb5d0STakashi Iwai 			}
4133e6feb5d0STakashi Iwai 		}
4134e6feb5d0STakashi Iwai 	}
4135e6feb5d0STakashi Iwai 	return changed;
4136e6feb5d0STakashi Iwai }
4137e6feb5d0STakashi Iwai 
4138d5ac0100STakashi Iwai /* check the jack status for power control */
4139d5ac0100STakashi Iwai static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4140d5ac0100STakashi Iwai {
4141d5ac0100STakashi Iwai 	if (!is_jack_detectable(codec, pin))
4142d5ac0100STakashi Iwai 		return true;
4143d5ac0100STakashi Iwai 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4144d5ac0100STakashi Iwai }
4145d5ac0100STakashi Iwai 
4146e6feb5d0STakashi Iwai /* power up/down the paths of the given pin according to the jack state;
4147e6feb5d0STakashi Iwai  * power = 0/1 : only power up/down if it matches with the jack state,
4148e6feb5d0STakashi Iwai  *       < 0   : force power up/down to follow the jack sate
4149e6feb5d0STakashi Iwai  *
4150e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4151e6feb5d0STakashi Iwai  */
4152e6feb5d0STakashi Iwai static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4153e6feb5d0STakashi Iwai 				    int power)
4154e6feb5d0STakashi Iwai {
4155e6feb5d0STakashi Iwai 	bool on;
4156e6feb5d0STakashi Iwai 
4157967b1307STakashi Iwai 	if (!codec->power_save_node)
4158e6feb5d0STakashi Iwai 		return 0;
4159e6feb5d0STakashi Iwai 
4160d5ac0100STakashi Iwai 	on = detect_pin_state(codec, pin);
4161d5ac0100STakashi Iwai 
4162e6feb5d0STakashi Iwai 	if (power >= 0 && on != power)
4163e6feb5d0STakashi Iwai 		return 0;
4164e6feb5d0STakashi Iwai 	return set_path_power(codec, pin, on, -1);
4165e6feb5d0STakashi Iwai }
4166e6feb5d0STakashi Iwai 
4167e6feb5d0STakashi Iwai static void pin_power_callback(struct hda_codec *codec,
4168e6feb5d0STakashi Iwai 			       struct hda_jack_callback *jack,
4169e6feb5d0STakashi Iwai 			       bool on)
4170e6feb5d0STakashi Iwai {
41712ebab40eSTakashi Iwai 	if (jack && jack->nid)
4172e6feb5d0STakashi Iwai 		sync_power_state_change(codec,
41732ebab40eSTakashi Iwai 					set_pin_power_jack(codec, jack->nid, on));
4174e6feb5d0STakashi Iwai }
4175e6feb5d0STakashi Iwai 
4176e6feb5d0STakashi Iwai /* callback only doing power up -- called at first */
4177e6feb5d0STakashi Iwai static void pin_power_up_callback(struct hda_codec *codec,
4178e6feb5d0STakashi Iwai 				  struct hda_jack_callback *jack)
4179e6feb5d0STakashi Iwai {
4180e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, true);
4181e6feb5d0STakashi Iwai }
4182e6feb5d0STakashi Iwai 
4183e6feb5d0STakashi Iwai /* callback only doing power down -- called at last */
4184e6feb5d0STakashi Iwai static void pin_power_down_callback(struct hda_codec *codec,
4185e6feb5d0STakashi Iwai 				    struct hda_jack_callback *jack)
4186e6feb5d0STakashi Iwai {
4187e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, false);
4188e6feb5d0STakashi Iwai }
4189e6feb5d0STakashi Iwai 
4190e6feb5d0STakashi Iwai /* set up the power up/down callbacks */
4191e6feb5d0STakashi Iwai static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4192e6feb5d0STakashi Iwai 			       const hda_nid_t *pins, bool on)
4193e6feb5d0STakashi Iwai {
4194e6feb5d0STakashi Iwai 	int i;
4195e6feb5d0STakashi Iwai 	hda_jack_callback_fn cb =
4196e6feb5d0STakashi Iwai 		on ? pin_power_up_callback : pin_power_down_callback;
4197e6feb5d0STakashi Iwai 
4198e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++) {
4199e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4200e6feb5d0STakashi Iwai 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4201e6feb5d0STakashi Iwai 		else
4202e6feb5d0STakashi Iwai 			set_path_power(codec, pins[i], true, -1);
4203e6feb5d0STakashi Iwai 	}
4204e6feb5d0STakashi Iwai }
4205e6feb5d0STakashi Iwai 
4206e6feb5d0STakashi Iwai /* enabled power callback to each available I/O pin with jack detections;
4207e6feb5d0STakashi Iwai  * the digital I/O pins are excluded because of the unreliable detectsion
4208e6feb5d0STakashi Iwai  */
4209e6feb5d0STakashi Iwai static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4210e6feb5d0STakashi Iwai {
4211e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4212e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4213e6feb5d0STakashi Iwai 	int i;
4214e6feb5d0STakashi Iwai 
4215967b1307STakashi Iwai 	if (!codec->power_save_node)
4216e6feb5d0STakashi Iwai 		return;
4217e6feb5d0STakashi Iwai 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4218e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4219e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4220e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4221e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4222e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4223e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4224e6feb5d0STakashi Iwai }
4225e6feb5d0STakashi Iwai 
4226e6feb5d0STakashi Iwai /* sync path power up/down with the jack states of given pins */
4227e6feb5d0STakashi Iwai static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4228e6feb5d0STakashi Iwai 				const hda_nid_t *pins)
4229e6feb5d0STakashi Iwai {
4230e6feb5d0STakashi Iwai 	int i;
4231e6feb5d0STakashi Iwai 
4232e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++)
4233e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4234e6feb5d0STakashi Iwai 			set_pin_power_jack(codec, pins[i], -1);
4235e6feb5d0STakashi Iwai }
4236e6feb5d0STakashi Iwai 
4237e6feb5d0STakashi Iwai /* sync path power up/down with pins; called at init and resume */
4238e6feb5d0STakashi Iwai static void sync_all_pin_power_ctls(struct hda_codec *codec)
4239e6feb5d0STakashi Iwai {
4240e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4241e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4242e6feb5d0STakashi Iwai 	int i;
4243e6feb5d0STakashi Iwai 
4244967b1307STakashi Iwai 	if (!codec->power_save_node)
4245e6feb5d0STakashi Iwai 		return;
4246e6feb5d0STakashi Iwai 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4247e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4248e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4249e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4250e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4251e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4252e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4253e6feb5d0STakashi Iwai }
42541da177e4SLinus Torvalds 
42555ccf835cSTakashi Iwai /* add fake paths if not present yet */
42565ccf835cSTakashi Iwai static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
42575ccf835cSTakashi Iwai 			   int num_pins, const hda_nid_t *pins)
42585ccf835cSTakashi Iwai {
42595ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
42605ccf835cSTakashi Iwai 	struct nid_path *path;
42615ccf835cSTakashi Iwai 	int i;
42625ccf835cSTakashi Iwai 
42635ccf835cSTakashi Iwai 	for (i = 0; i < num_pins; i++) {
42645ccf835cSTakashi Iwai 		if (!pins[i])
42655ccf835cSTakashi Iwai 			break;
42665ccf835cSTakashi Iwai 		if (get_nid_path(codec, nid, pins[i], 0))
42675ccf835cSTakashi Iwai 			continue;
42685ccf835cSTakashi Iwai 		path = snd_array_new(&spec->paths);
42695ccf835cSTakashi Iwai 		if (!path)
42705ccf835cSTakashi Iwai 			return -ENOMEM;
42715ccf835cSTakashi Iwai 		memset(path, 0, sizeof(*path));
42725ccf835cSTakashi Iwai 		path->depth = 2;
42735ccf835cSTakashi Iwai 		path->path[0] = nid;
42745ccf835cSTakashi Iwai 		path->path[1] = pins[i];
42755ccf835cSTakashi Iwai 		path->active = true;
42765ccf835cSTakashi Iwai 	}
42775ccf835cSTakashi Iwai 	return 0;
42785ccf835cSTakashi Iwai }
42795ccf835cSTakashi Iwai 
42805ccf835cSTakashi Iwai /* create fake paths to all outputs from beep */
42815ccf835cSTakashi Iwai static int add_fake_beep_paths(struct hda_codec *codec)
42825ccf835cSTakashi Iwai {
42835ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
42845ccf835cSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
42855ccf835cSTakashi Iwai 	hda_nid_t nid = spec->beep_nid;
42865ccf835cSTakashi Iwai 	int err;
42875ccf835cSTakashi Iwai 
4288967b1307STakashi Iwai 	if (!codec->power_save_node || !nid)
42895ccf835cSTakashi Iwai 		return 0;
42905ccf835cSTakashi Iwai 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
42915ccf835cSTakashi Iwai 	if (err < 0)
42925ccf835cSTakashi Iwai 		return err;
42935ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
42945ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
42955ccf835cSTakashi Iwai 		if (err < 0)
42965ccf835cSTakashi Iwai 			return err;
42975ccf835cSTakashi Iwai 	}
42985ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
42995ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
43005ccf835cSTakashi Iwai 				     cfg->speaker_pins);
43015ccf835cSTakashi Iwai 		if (err < 0)
43025ccf835cSTakashi Iwai 			return err;
43035ccf835cSTakashi Iwai 	}
43045ccf835cSTakashi Iwai 	return 0;
43055ccf835cSTakashi Iwai }
43065ccf835cSTakashi Iwai 
43075ccf835cSTakashi Iwai /* power up/down beep widget and its output paths */
43085ccf835cSTakashi Iwai static void beep_power_hook(struct hda_beep *beep, bool on)
43095ccf835cSTakashi Iwai {
43105ccf835cSTakashi Iwai 	set_path_power(beep->codec, beep->nid, -1, on);
43115ccf835cSTakashi Iwai }
43125ccf835cSTakashi Iwai 
43136b275b14STakashi Iwai /**
43146b275b14STakashi Iwai  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
43156b275b14STakashi Iwai  * @codec: the HDA codec
43166b275b14STakashi Iwai  * @pin: NID of pin to fix
43176b275b14STakashi Iwai  */
43186b275b14STakashi Iwai int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
43196b275b14STakashi Iwai {
43206b275b14STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
43216b275b14STakashi Iwai 	struct nid_path *path;
43226b275b14STakashi Iwai 
43236b275b14STakashi Iwai 	path = snd_array_new(&spec->paths);
43246b275b14STakashi Iwai 	if (!path)
43256b275b14STakashi Iwai 		return -ENOMEM;
43266b275b14STakashi Iwai 	memset(path, 0, sizeof(*path));
43276b275b14STakashi Iwai 	path->depth = 1;
43286b275b14STakashi Iwai 	path->path[0] = pin;
43296b275b14STakashi Iwai 	path->active = true;
43306b275b14STakashi Iwai 	path->pin_fixed = true;
43316b275b14STakashi Iwai 	path->stream_enabled = true;
43326b275b14STakashi Iwai 	return 0;
43336b275b14STakashi Iwai }
43346b275b14STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
43356b275b14STakashi Iwai 
43361da177e4SLinus Torvalds /*
4337352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
43381da177e4SLinus Torvalds  */
4339352f7f91STakashi Iwai 
4340352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
4341caf3c043SMichał Mirosław static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
43421da177e4SLinus Torvalds {
434360ea8ca2STakashi Iwai 	int i;
434460ea8ca2STakashi Iwai 	bool present = false;
43451da177e4SLinus Torvalds 
4346352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4347352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4348352f7f91STakashi Iwai 		if (!nid)
4349352f7f91STakashi Iwai 			break;
43500b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
43510b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
43520b4df931STakashi Iwai 			continue;
435360ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
435460ea8ca2STakashi Iwai 			present = true;
43551da177e4SLinus Torvalds 	}
4356352f7f91STakashi Iwai 	return present;
43571da177e4SLinus Torvalds }
43581da177e4SLinus Torvalds 
4359352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
4360caf3c043SMichał Mirosław static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
4361e80c60f3STakashi Iwai 			int *paths, bool mute)
43621da177e4SLinus Torvalds {
4363352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4364352f7f91STakashi Iwai 	int i;
43651da177e4SLinus Torvalds 
4366352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4367352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4368967303daSTakashi Iwai 		unsigned int val, oldval;
4369352f7f91STakashi Iwai 		if (!nid)
4370352f7f91STakashi Iwai 			break;
43717eebffd3STakashi Iwai 
4372e6feb5d0STakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4373e6feb5d0STakashi Iwai 		if (oldval & PIN_IN)
4374e6feb5d0STakashi Iwai 			continue; /* no mute for inputs */
4375e6feb5d0STakashi Iwai 
43767eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
4377e80c60f3STakashi Iwai 			struct nid_path *path;
4378e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
4379e80c60f3STakashi Iwai 
4380e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4381e80c60f3STakashi Iwai 			if (!path)
4382e80c60f3STakashi Iwai 				continue;
4383e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4384e80c60f3STakashi Iwai 			if (!mute_nid)
4385e80c60f3STakashi Iwai 				continue;
43867eebffd3STakashi Iwai 			if (mute)
4387e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
43887eebffd3STakashi Iwai 			else
4389e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
43907eebffd3STakashi Iwai 			continue;
4391e6feb5d0STakashi Iwai 		} else {
4392352f7f91STakashi Iwai 			/* don't reset VREF value in case it's controlling
4393352f7f91STakashi Iwai 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4394352f7f91STakashi Iwai 			 */
43952c12c30dSTakashi Iwai 			if (spec->keep_vref_in_automute)
4396967303daSTakashi Iwai 				val = oldval & ~PIN_HP;
43972c12c30dSTakashi Iwai 			else
4398352f7f91STakashi Iwai 				val = 0;
43992c12c30dSTakashi Iwai 			if (!mute)
4400967303daSTakashi Iwai 				val |= oldval;
4401e6feb5d0STakashi Iwai 			/* here we call update_pin_ctl() so that the pinctl is
4402e6feb5d0STakashi Iwai 			 * changed without changing the pinctl target value;
4403e6feb5d0STakashi Iwai 			 * the original target value will be still referred at
4404e6feb5d0STakashi Iwai 			 * the init / resume again
44052c12c30dSTakashi Iwai 			 */
44062c12c30dSTakashi Iwai 			update_pin_ctl(codec, nid, val);
4407e6feb5d0STakashi Iwai 		}
4408e6feb5d0STakashi Iwai 
4409d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
4410967b1307STakashi Iwai 		if (codec->power_save_node) {
4411e6feb5d0STakashi Iwai 			bool on = !mute;
4412e6feb5d0STakashi Iwai 			if (on)
4413d5ac0100STakashi Iwai 				on = detect_pin_state(codec, nid);
4414e6feb5d0STakashi Iwai 			set_path_power(codec, nid, on, -1);
4415e6feb5d0STakashi Iwai 		}
4416352f7f91STakashi Iwai 	}
4417352f7f91STakashi Iwai }
44181da177e4SLinus Torvalds 
4419dda42bd0STakashi Iwai /**
4420dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
4421dda42bd0STakashi Iwai  * @codec: the HDA codec
4422dda42bd0STakashi Iwai  *
4423dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
4424dda42bd0STakashi Iwai  */
44255d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
4426352f7f91STakashi Iwai {
4427352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4428e80c60f3STakashi Iwai 	int *paths;
4429352f7f91STakashi Iwai 	int on;
4430352f7f91STakashi Iwai 
4431352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
4432352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
4433352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
4434352f7f91STakashi Iwai 	 */
4435e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4436e80c60f3STakashi Iwai 		paths = spec->out_paths;
4437e80c60f3STakashi Iwai 	else
4438e80c60f3STakashi Iwai 		paths = spec->hp_paths;
4439352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4440e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4441352f7f91STakashi Iwai 
4442352f7f91STakashi Iwai 	if (!spec->automute_speaker)
4443352f7f91STakashi Iwai 		on = 0;
4444352f7f91STakashi Iwai 	else
4445352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
4446352f7f91STakashi Iwai 	on |= spec->master_mute;
444747b9ddb8STakashi Iwai 	spec->speaker_muted = on;
4448e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4449e80c60f3STakashi Iwai 		paths = spec->out_paths;
4450e80c60f3STakashi Iwai 	else
4451e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
4452352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4453e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
4454352f7f91STakashi Iwai 
4455352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
4456352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4457352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4458352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4459352f7f91STakashi Iwai 		return;
4460352f7f91STakashi Iwai 	if (!spec->automute_lo)
4461352f7f91STakashi Iwai 		on = 0;
4462352f7f91STakashi Iwai 	else
4463352f7f91STakashi Iwai 		on = spec->hp_jack_present;
4464352f7f91STakashi Iwai 	on |= spec->master_mute;
446547b9ddb8STakashi Iwai 	spec->line_out_muted = on;
4466e80c60f3STakashi Iwai 	paths = spec->out_paths;
4467352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4468e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
4469352f7f91STakashi Iwai }
44702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4471352f7f91STakashi Iwai 
4472352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
4473352f7f91STakashi Iwai {
4474352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4475352f7f91STakashi Iwai 	if (spec->automute_hook)
4476352f7f91STakashi Iwai 		spec->automute_hook(codec);
4477352f7f91STakashi Iwai 	else
44785d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
44797eebffd3STakashi Iwai 
44809ab0cb30STakashi Iwai 	/* sync the whole vmaster followers to reflect the new auto-mute status */
44817eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
44827eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4483352f7f91STakashi Iwai }
4484352f7f91STakashi Iwai 
4485dda42bd0STakashi Iwai /**
4486dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4487dda42bd0STakashi Iwai  * @codec: the HDA codec
4488dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4489dda42bd0STakashi Iwai  */
44901a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
44911a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4492352f7f91STakashi Iwai {
4493352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
449492603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
449592603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4496352f7f91STakashi Iwai 
449792603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
449892603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
449992603c59STakashi Iwai 		pins++;
450092603c59STakashi Iwai 		num_pins--;
450192603c59STakashi Iwai 	}
450292603c59STakashi Iwai 
450392603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4504352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4505352f7f91STakashi Iwai 		return;
4506352f7f91STakashi Iwai 	call_update_outputs(codec);
4507352f7f91STakashi Iwai }
45082698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4509352f7f91STakashi Iwai 
4510dda42bd0STakashi Iwai /**
4511dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4512dda42bd0STakashi Iwai  * @codec: the HDA codec
4513dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4514dda42bd0STakashi Iwai  */
45151a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
45161a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4517352f7f91STakashi Iwai {
4518352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4519352f7f91STakashi Iwai 
4520352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4521352f7f91STakashi Iwai 		return;
4522352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4523352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4524352f7f91STakashi Iwai 		return;
4525352f7f91STakashi Iwai 
4526352f7f91STakashi Iwai 	spec->line_jack_present =
4527352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4528352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4529352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4530352f7f91STakashi Iwai 		return;
4531352f7f91STakashi Iwai 	call_update_outputs(codec);
4532352f7f91STakashi Iwai }
45332698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4534352f7f91STakashi Iwai 
4535dda42bd0STakashi Iwai /**
4536dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4537dda42bd0STakashi Iwai  * @codec: the HDA codec
4538dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4539dda42bd0STakashi Iwai  */
45401a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
45411a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4542352f7f91STakashi Iwai {
4543352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4544352f7f91STakashi Iwai 	int i;
4545352f7f91STakashi Iwai 
4546352f7f91STakashi Iwai 	if (!spec->auto_mic)
4547352f7f91STakashi Iwai 		return;
4548352f7f91STakashi Iwai 
4549352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
45500b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
45510b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
45520b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
45530b4df931STakashi Iwai 			continue;
455460ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4555352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4556352f7f91STakashi Iwai 			return;
4557352f7f91STakashi Iwai 		}
4558352f7f91STakashi Iwai 	}
4559352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
45601da177e4SLinus Torvalds }
45612698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
45621da177e4SLinus Torvalds 
456377afe0e9STakashi Iwai /* call appropriate hooks */
45641a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
45651a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
456677afe0e9STakashi Iwai {
456777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
456877afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
456977afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
457077afe0e9STakashi Iwai 	else
457177afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
457277afe0e9STakashi Iwai }
457377afe0e9STakashi Iwai 
457477afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
45751a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
457677afe0e9STakashi Iwai {
457777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
457877afe0e9STakashi Iwai 	if (spec->line_automute_hook)
457977afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
458077afe0e9STakashi Iwai 	else
458177afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
458277afe0e9STakashi Iwai }
458377afe0e9STakashi Iwai 
458477afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
45851a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
458677afe0e9STakashi Iwai {
458777afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
458877afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
458977afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
459077afe0e9STakashi Iwai 	else
459177afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
459277afe0e9STakashi Iwai }
459377afe0e9STakashi Iwai 
4594963afde9STakashi Iwai /* update jack retasking */
4595963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4596963afde9STakashi Iwai {
4597963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4598963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4599963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4600963afde9STakashi Iwai }
4601963afde9STakashi Iwai 
46021da177e4SLinus Torvalds /*
4603352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
46041da177e4SLinus Torvalds  */
4605352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4606352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4607352f7f91STakashi Iwai {
4608352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4609352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4610352f7f91STakashi Iwai 	static const char * const texts3[] = {
4611352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
46121da177e4SLinus Torvalds 	};
46131da177e4SLinus Torvalds 
4614352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4615352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4616352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4617352f7f91STakashi Iwai }
4618352f7f91STakashi Iwai 
4619352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4620352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4621352f7f91STakashi Iwai {
4622352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4623352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4624352f7f91STakashi Iwai 	unsigned int val = 0;
4625352f7f91STakashi Iwai 	if (spec->automute_speaker)
4626352f7f91STakashi Iwai 		val++;
4627352f7f91STakashi Iwai 	if (spec->automute_lo)
4628352f7f91STakashi Iwai 		val++;
4629352f7f91STakashi Iwai 
4630352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4631352f7f91STakashi Iwai 	return 0;
4632352f7f91STakashi Iwai }
4633352f7f91STakashi Iwai 
4634352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4635352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4636352f7f91STakashi Iwai {
4637352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4638352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4639352f7f91STakashi Iwai 
4640352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4641352f7f91STakashi Iwai 	case 0:
4642352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4643352f7f91STakashi Iwai 			return 0;
4644352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4645352f7f91STakashi Iwai 		spec->automute_lo = 0;
4646352f7f91STakashi Iwai 		break;
4647352f7f91STakashi Iwai 	case 1:
4648352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4649352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4650352f7f91STakashi Iwai 				return 0;
4651352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4652352f7f91STakashi Iwai 			spec->automute_lo = 0;
4653352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4654352f7f91STakashi Iwai 			if (spec->automute_lo)
4655352f7f91STakashi Iwai 				return 0;
4656352f7f91STakashi Iwai 			spec->automute_lo = 1;
4657352f7f91STakashi Iwai 		} else
4658352f7f91STakashi Iwai 			return -EINVAL;
4659352f7f91STakashi Iwai 		break;
4660352f7f91STakashi Iwai 	case 2:
4661352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4662352f7f91STakashi Iwai 			return -EINVAL;
4663352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4664352f7f91STakashi Iwai 			return 0;
4665352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4666352f7f91STakashi Iwai 		spec->automute_lo = 1;
4667352f7f91STakashi Iwai 		break;
4668352f7f91STakashi Iwai 	default:
4669352f7f91STakashi Iwai 		return -EINVAL;
4670352f7f91STakashi Iwai 	}
4671352f7f91STakashi Iwai 	call_update_outputs(codec);
4672352f7f91STakashi Iwai 	return 1;
4673352f7f91STakashi Iwai }
4674352f7f91STakashi Iwai 
4675352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4676352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4677352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4678352f7f91STakashi Iwai 	.info = automute_mode_info,
4679352f7f91STakashi Iwai 	.get = automute_mode_get,
4680352f7f91STakashi Iwai 	.put = automute_mode_put,
4681352f7f91STakashi Iwai };
4682352f7f91STakashi Iwai 
4683352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4684352f7f91STakashi Iwai {
4685352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4686352f7f91STakashi Iwai 
468712c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4688352f7f91STakashi Iwai 		return -ENOMEM;
4689352f7f91STakashi Iwai 	return 0;
4690352f7f91STakashi Iwai }
4691352f7f91STakashi Iwai 
4692352f7f91STakashi Iwai /*
4693352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4694352f7f91STakashi Iwai  * Set up appropriately if really supported
4695352f7f91STakashi Iwai  */
4696352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4697352f7f91STakashi Iwai {
4698352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4699352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4700352f7f91STakashi Iwai 	int present = 0;
4701352f7f91STakashi Iwai 	int i, err;
4702352f7f91STakashi Iwai 
4703f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4704f72706beSTakashi Iwai 		return 0;
4705f72706beSTakashi Iwai 
4706352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4707352f7f91STakashi Iwai 		present++;
4708352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4709352f7f91STakashi Iwai 		present++;
4710352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4711352f7f91STakashi Iwai 		present++;
4712352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4713352f7f91STakashi Iwai 		return 0;
4714352f7f91STakashi Iwai 
4715352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4716352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4717352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4718352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4719352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4720352f7f91STakashi Iwai 	}
4721352f7f91STakashi Iwai 
4722352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4723352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4724352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4725352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4726352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4727352f7f91STakashi Iwai 	}
4728352f7f91STakashi Iwai 
4729352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4730352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4731352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4732352f7f91STakashi Iwai 			continue;
47334e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
473462f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
473577afe0e9STakashi Iwai 						    call_hp_automute);
4736352f7f91STakashi Iwai 		spec->detect_hp = 1;
4737352f7f91STakashi Iwai 	}
4738352f7f91STakashi Iwai 
4739352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4740352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4741352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4742352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4743352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4744352f7f91STakashi Iwai 					continue;
47454e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4746352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
474777afe0e9STakashi Iwai 								    call_line_automute);
4748352f7f91STakashi Iwai 				spec->detect_lo = 1;
4749352f7f91STakashi Iwai 			}
4750352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4751352f7f91STakashi Iwai 	}
4752352f7f91STakashi Iwai 
4753352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4754352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4755352f7f91STakashi Iwai 
4756352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4757352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4758352f7f91STakashi Iwai 
4759352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4760352f7f91STakashi Iwai 		/* create a control for automute mode */
4761352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4762352f7f91STakashi Iwai 		if (err < 0)
4763352f7f91STakashi Iwai 			return err;
4764352f7f91STakashi Iwai 	}
4765352f7f91STakashi Iwai 	return 0;
4766352f7f91STakashi Iwai }
4767352f7f91STakashi Iwai 
4768352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4769352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4770352f7f91STakashi Iwai {
4771352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4772352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4773352f7f91STakashi Iwai 	int i;
4774352f7f91STakashi Iwai 
4775352f7f91STakashi Iwai 	imux = &spec->input_mux;
4776352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4777352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4778352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4779352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4780352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4781352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4782352f7f91STakashi Iwai 	}
4783352f7f91STakashi Iwai 
4784352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4785352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4786352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4787352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
478877afe0e9STakashi Iwai 						    call_mic_autoswitch);
4789352f7f91STakashi Iwai 	return true;
4790352f7f91STakashi Iwai }
4791352f7f91STakashi Iwai 
4792352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4793352f7f91STakashi Iwai {
4794352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4795352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4796352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4797352f7f91STakashi Iwai }
4798352f7f91STakashi Iwai 
4799352f7f91STakashi Iwai /*
4800352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4801352f7f91STakashi Iwai  * Set up if really supported
4802352f7f91STakashi Iwai  */
4803352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4804352f7f91STakashi Iwai {
4805352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4806352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4807352f7f91STakashi Iwai 	unsigned int types;
4808352f7f91STakashi Iwai 	int i, num_pins;
4809352f7f91STakashi Iwai 
4810d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4811d12daf6fSTakashi Iwai 		return 0;
4812d12daf6fSTakashi Iwai 
4813352f7f91STakashi Iwai 	types = 0;
4814352f7f91STakashi Iwai 	num_pins = 0;
4815352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4816352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4817352f7f91STakashi Iwai 		unsigned int attr;
4818352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4819352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4820352f7f91STakashi Iwai 		if (types & (1 << attr))
4821352f7f91STakashi Iwai 			return 0; /* already occupied */
4822352f7f91STakashi Iwai 		switch (attr) {
4823352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4824352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4825352f7f91STakashi Iwai 				return 0; /* invalid type */
4826352f7f91STakashi Iwai 			break;
4827352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4828352f7f91STakashi Iwai 			return 0; /* invalid entry */
4829352f7f91STakashi Iwai 		default:
4830352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4831352f7f91STakashi Iwai 				return 0; /* invalid type */
4832352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4833352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4834352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4835352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4836352f7f91STakashi Iwai 				return 0; /* no unsol support */
4837352f7f91STakashi Iwai 			break;
4838352f7f91STakashi Iwai 		}
4839352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4840352f7f91STakashi Iwai 			return 0;
4841352f7f91STakashi Iwai 		types |= (1 << attr);
4842352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4843352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4844352f7f91STakashi Iwai 		num_pins++;
4845352f7f91STakashi Iwai 	}
4846352f7f91STakashi Iwai 
4847352f7f91STakashi Iwai 	if (num_pins < 2)
4848352f7f91STakashi Iwai 		return 0;
4849352f7f91STakashi Iwai 
4850352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4851352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4852352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4853352f7f91STakashi Iwai 	 */
4854352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4855352f7f91STakashi Iwai 	     compare_attr, NULL);
4856352f7f91STakashi Iwai 
4857352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4858352f7f91STakashi Iwai 		return 0;
4859352f7f91STakashi Iwai 
4860352f7f91STakashi Iwai 	spec->auto_mic = 1;
4861352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4862352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
48634e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4864352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4865352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4866352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4867352f7f91STakashi Iwai 
4868352f7f91STakashi Iwai 	return 0;
4869352f7f91STakashi Iwai }
4870352f7f91STakashi Iwai 
4871dda42bd0STakashi Iwai /**
4872dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4873dda42bd0STakashi Iwai  * into power down
4874dda42bd0STakashi Iwai  * @codec: the HDA codec
4875dda42bd0STakashi Iwai  * @nid: NID to evalute
4876dda42bd0STakashi Iwai  * @power_state: target power state
4877dda42bd0STakashi Iwai  */
4878dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
487955196fffSTakashi Iwai 						  hda_nid_t nid,
488055196fffSTakashi Iwai 						  unsigned int power_state)
488155196fffSTakashi Iwai {
4882b6c09b3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4883b6c09b3cSTakashi Iwai 
4884b6c09b3cSTakashi Iwai 	if (!spec->power_down_unused && !codec->power_save_node)
4885b6c09b3cSTakashi Iwai 		return power_state;
48867639a06cSTakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
488755196fffSTakashi Iwai 		return power_state;
488855196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
488955196fffSTakashi Iwai 		return power_state;
4890b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
489155196fffSTakashi Iwai 		return power_state;
489255196fffSTakashi Iwai 	return AC_PWRST_D3;
489355196fffSTakashi Iwai }
4894dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
489555196fffSTakashi Iwai 
4896ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4897ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4898ebb93c05STakashi Iwai {
4899ebb93c05STakashi Iwai 	int i, nums;
4900ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4901ebb93c05STakashi Iwai 	bool has_amp;
4902ebb93c05STakashi Iwai 
4903ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4904ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4905ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4906ebb93c05STakashi Iwai 		if (has_amp)
4907ef403edbSTakashi Iwai 			update_amp(codec, mix, HDA_INPUT, i,
4908ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4909ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4910ef403edbSTakashi Iwai 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
4911ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4912ebb93c05STakashi Iwai 	}
4913ebb93c05STakashi Iwai }
4914352f7f91STakashi Iwai 
4915dda42bd0STakashi Iwai /**
4916e6feb5d0STakashi Iwai  * snd_hda_gen_stream_pm - Stream power management callback
4917e6feb5d0STakashi Iwai  * @codec: the HDA codec
4918e6feb5d0STakashi Iwai  * @nid: audio widget
4919e6feb5d0STakashi Iwai  * @on: power on/off flag
4920e6feb5d0STakashi Iwai  *
4921967b1307STakashi Iwai  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
4922e6feb5d0STakashi Iwai  */
4923e6feb5d0STakashi Iwai void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
4924e6feb5d0STakashi Iwai {
4925967b1307STakashi Iwai 	if (codec->power_save_node)
4926e6feb5d0STakashi Iwai 		set_path_power(codec, nid, -1, on);
4927e6feb5d0STakashi Iwai }
4928e6feb5d0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
4929e6feb5d0STakashi Iwai 
4930e6feb5d0STakashi Iwai /**
4931dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
4932dda42bd0STakashi Iwai  * set up the hda_gen_spec
4933dda42bd0STakashi Iwai  * @codec: the HDA codec
4934dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
49359eb413e5STakashi Iwai  *
49369eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
4937352f7f91STakashi Iwai  * or a negative error code
4938352f7f91STakashi Iwai  */
4939352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
49409eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
4941352f7f91STakashi Iwai {
4942352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4943352f7f91STakashi Iwai 	int err;
4944352f7f91STakashi Iwai 
49451c70a583STakashi Iwai 	parse_user_hints(codec);
49461c70a583STakashi Iwai 
4947*e65bf997SJaroslav Kysela 	if (spec->vmaster_mute_led || spec->mic_mute_led)
4948*e65bf997SJaroslav Kysela 		snd_ctl_led_request();
4949*e65bf997SJaroslav Kysela 
4950e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
4951e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
4952e4a395e7STakashi Iwai 
49539eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
49549eb413e5STakashi Iwai 		spec->autocfg = *cfg;
49559eb413e5STakashi Iwai 		cfg = &spec->autocfg;
49569eb413e5STakashi Iwai 	}
49579eb413e5STakashi Iwai 
495898bd1115STakashi Iwai 	if (!spec->main_out_badness)
495998bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
496098bd1115STakashi Iwai 	if (!spec->extra_out_badness)
496198bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
496298bd1115STakashi Iwai 
49636fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
49646fc4cb97SDavid Henningsson 
4965352f7f91STakashi Iwai 	if (!cfg->line_outs) {
4966352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
4967352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
4968352f7f91STakashi Iwai 			spec->no_analog = 1;
4969352f7f91STakashi Iwai 			goto dig_only;
4970352f7f91STakashi Iwai 		}
4971c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
4972352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
4973352f7f91STakashi Iwai 	}
4974352f7f91STakashi Iwai 
4975352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
4976352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
4977352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
4978352f7f91STakashi Iwai 		/* use HP as primary out */
4979352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4980352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4981352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4982352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
4983352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
4984352f7f91STakashi Iwai 		cfg->hp_outs = 0;
4985352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
4986352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
4987352f7f91STakashi Iwai 	}
4988352f7f91STakashi Iwai 
4989352f7f91STakashi Iwai 	err = parse_output_paths(codec);
4990352f7f91STakashi Iwai 	if (err < 0)
4991352f7f91STakashi Iwai 		return err;
4992352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
4993352f7f91STakashi Iwai 	if (err < 0)
4994352f7f91STakashi Iwai 		return err;
4995352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
4996352f7f91STakashi Iwai 	if (err < 0)
4997352f7f91STakashi Iwai 		return err;
4998352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
4999352f7f91STakashi Iwai 	if (err < 0)
5000352f7f91STakashi Iwai 		return err;
5001352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
5002352f7f91STakashi Iwai 	if (err < 0)
5003352f7f91STakashi Iwai 		return err;
500438cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
500538cf6f1aSTakashi Iwai 	if (err < 0)
500638cf6f1aSTakashi Iwai 		return err;
5007c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
5008c30aa7b2STakashi Iwai 	if (err < 0)
5009c30aa7b2STakashi Iwai 		return err;
5010967303daSTakashi Iwai 	err = create_hp_mic(codec);
5011352f7f91STakashi Iwai 	if (err < 0)
5012352f7f91STakashi Iwai 		return err;
5013352f7f91STakashi Iwai 	err = create_input_ctls(codec);
5014352f7f91STakashi Iwai 	if (err < 0)
5015352f7f91STakashi Iwai 		return err;
5016352f7f91STakashi Iwai 
5017e6feb5d0STakashi Iwai 	/* add power-down pin callbacks at first */
5018e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, false);
5019e6feb5d0STakashi Iwai 
5020a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
5021a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
5022a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
5023a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5024a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
5025a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
5026a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5027a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
5028352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
5029352f7f91STakashi Iwai 					  spec->const_channel_count);
5030352f7f91STakashi Iwai 
5031352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
5032352f7f91STakashi Iwai 	if (err < 0)
5033352f7f91STakashi Iwai 		return err;
5034352f7f91STakashi Iwai 
5035352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
5036352f7f91STakashi Iwai 	if (err < 0)
5037352f7f91STakashi Iwai 		return err;
5038352f7f91STakashi Iwai 
5039352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
5040352f7f91STakashi Iwai 	if (err < 0)
5041352f7f91STakashi Iwai 		return err;
5042352f7f91STakashi Iwai 
5043f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
5044f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
504574f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
504674f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
5047f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
5048f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
5049f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
5050f1e762ddSTakashi Iwai 		if (err < 0)
5051f1e762ddSTakashi Iwai 			return err;
5052f1e762ddSTakashi Iwai 	}
5053f1e762ddSTakashi Iwai 
5054f1e762ddSTakashi Iwai 
5055352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
5056352f7f91STakashi Iwai 	if (err < 0)
5057352f7f91STakashi Iwai 		return err;
5058352f7f91STakashi Iwai 
5059352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
5060352f7f91STakashi Iwai 	if (err < 0)
5061352f7f91STakashi Iwai 		return err;
5062352f7f91STakashi Iwai 
5063ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
5064ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
5065ced4cefcSTakashi Iwai 	 */
5066ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
5067ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
5068ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
5069ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
5070ced4cefcSTakashi Iwai 		if (err < 0)
5071ced4cefcSTakashi Iwai 			return err;
5072ced4cefcSTakashi Iwai 	}
5073ced4cefcSTakashi Iwai 
5074f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
5075978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
5076978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
5077978e77e7STakashi Iwai 						    cfg->line_out_pins);
5078978e77e7STakashi Iwai 			if (err < 0)
5079978e77e7STakashi Iwai 				return err;
5080978e77e7STakashi Iwai 		}
5081978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
5082978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
5083978e77e7STakashi Iwai 						    cfg->hp_pins);
5084978e77e7STakashi Iwai 			if (err < 0)
5085978e77e7STakashi Iwai 				return err;
5086978e77e7STakashi Iwai 		}
5087978e77e7STakashi Iwai 	}
5088978e77e7STakashi Iwai 
5089e6feb5d0STakashi Iwai 	/* add power-up pin callbacks at last */
5090e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, true);
5091e6feb5d0STakashi Iwai 
5092ebb93c05STakashi Iwai 	/* mute all aamix input initially */
5093ebb93c05STakashi Iwai 	if (spec->mixer_nid)
5094ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
5095ebb93c05STakashi Iwai 
5096352f7f91STakashi Iwai  dig_only:
5097352f7f91STakashi Iwai 	parse_digital(codec);
5098352f7f91STakashi Iwai 
509949fb1897STakashi Iwai 	if (spec->power_down_unused || codec->power_save_node) {
510024fef902STakashi Iwai 		if (!codec->power_filter)
510155196fffSTakashi Iwai 			codec->power_filter = snd_hda_gen_path_power_filter;
510249fb1897STakashi Iwai 		if (!codec->patch_ops.stream_pm)
510349fb1897STakashi Iwai 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
510449fb1897STakashi Iwai 	}
510555196fffSTakashi Iwai 
51067504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
51077504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
51087504b6cdSTakashi Iwai 		if (err < 0)
51097504b6cdSTakashi Iwai 			return err;
5110967b1307STakashi Iwai 		if (codec->beep && codec->power_save_node) {
51115ccf835cSTakashi Iwai 			err = add_fake_beep_paths(codec);
51125ccf835cSTakashi Iwai 			if (err < 0)
51135ccf835cSTakashi Iwai 				return err;
51145ccf835cSTakashi Iwai 			codec->beep->power_hook = beep_power_hook;
51155ccf835cSTakashi Iwai 		}
51167504b6cdSTakashi Iwai 	}
51177504b6cdSTakashi Iwai 
5118352f7f91STakashi Iwai 	return 1;
5119352f7f91STakashi Iwai }
51202698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
5121352f7f91STakashi Iwai 
5122352f7f91STakashi Iwai 
5123352f7f91STakashi Iwai /*
5124352f7f91STakashi Iwai  * Build control elements
5125352f7f91STakashi Iwai  */
5126352f7f91STakashi Iwai 
51279ab0cb30STakashi Iwai /* follower controls for virtual master */
51289ab0cb30STakashi Iwai static const char * const follower_pfxs[] = {
5129352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
5130352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
5131352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
5132ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
5133ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
513403ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
5135352f7f91STakashi Iwai 	NULL,
5136352f7f91STakashi Iwai };
5137352f7f91STakashi Iwai 
5138dda42bd0STakashi Iwai /**
5139dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
5140dda42bd0STakashi Iwai  * @codec: the HDA codec
5141dda42bd0STakashi Iwai  *
5142dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
5143dda42bd0STakashi Iwai  */
5144352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
5145352f7f91STakashi Iwai {
5146352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5147352f7f91STakashi Iwai 	int err;
5148352f7f91STakashi Iwai 
514936502d02STakashi Iwai 	if (spec->kctls.used) {
5150352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5151352f7f91STakashi Iwai 		if (err < 0)
5152352f7f91STakashi Iwai 			return err;
515336502d02STakashi Iwai 	}
5154352f7f91STakashi Iwai 
5155352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
5156352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
5157352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5158352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5159bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
5160352f7f91STakashi Iwai 		if (err < 0)
5161352f7f91STakashi Iwai 			return err;
5162352f7f91STakashi Iwai 		if (!spec->no_analog) {
5163352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
5164352f7f91STakashi Iwai 							    &spec->multiout);
5165352f7f91STakashi Iwai 			if (err < 0)
5166352f7f91STakashi Iwai 				return err;
5167352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
5168352f7f91STakashi Iwai 		}
5169352f7f91STakashi Iwai 	}
5170352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
5171352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5172352f7f91STakashi Iwai 		if (err < 0)
5173352f7f91STakashi Iwai 			return err;
5174352f7f91STakashi Iwai 	}
5175352f7f91STakashi Iwai 
5176352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
51777480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5178352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5179352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
51809ab0cb30STakashi Iwai 					  spec->vmaster_tlv, follower_pfxs,
5181*e65bf997SJaroslav Kysela 					  "Playback Volume", 0);
5182352f7f91STakashi Iwai 		if (err < 0)
5183352f7f91STakashi Iwai 			return err;
5184352f7f91STakashi Iwai 	}
51857480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5186352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5187352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
51889ab0cb30STakashi Iwai 					    NULL, follower_pfxs,
5189*e65bf997SJaroslav Kysela 					    "Playback Switch", true,
5190*e65bf997SJaroslav Kysela 					    spec->vmaster_mute_led ?
5191*e65bf997SJaroslav Kysela 						SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
5192*e65bf997SJaroslav Kysela 					    &spec->vmaster_mute.sw_kctl);
5193352f7f91STakashi Iwai 		if (err < 0)
5194352f7f91STakashi Iwai 			return err;
5195b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
5196*e65bf997SJaroslav Kysela 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
5197b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5198b63eae0aSTakashi Iwai 		}
5199352f7f91STakashi Iwai 	}
5200352f7f91STakashi Iwai 
5201352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
5202352f7f91STakashi Iwai 
5203352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5204352f7f91STakashi Iwai 	if (err < 0)
5205352f7f91STakashi Iwai 		return err;
5206352f7f91STakashi Iwai 
5207352f7f91STakashi Iwai 	return 0;
5208352f7f91STakashi Iwai }
52092698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5210352f7f91STakashi Iwai 
5211352f7f91STakashi Iwai 
5212352f7f91STakashi Iwai /*
5213352f7f91STakashi Iwai  * PCM definitions
5214352f7f91STakashi Iwai  */
5215352f7f91STakashi Iwai 
5216e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5217e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
5218e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
5219e6b85f3cSTakashi Iwai 				   int action)
5220e6b85f3cSTakashi Iwai {
5221e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5222e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
5223e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5224e6b85f3cSTakashi Iwai }
5225e6b85f3cSTakashi Iwai 
5226ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5227ac2e8736STakashi Iwai 				  struct hda_codec *codec,
5228ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
5229ac2e8736STakashi Iwai 				  int action)
5230ac2e8736STakashi Iwai {
5231ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5232ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
5233ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5234ac2e8736STakashi Iwai }
5235ac2e8736STakashi Iwai 
5236352f7f91STakashi Iwai /*
5237352f7f91STakashi Iwai  * Analog playback callbacks
5238352f7f91STakashi Iwai  */
5239352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5240352f7f91STakashi Iwai 			     struct hda_codec *codec,
5241352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
5242352f7f91STakashi Iwai {
5243352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
524438cf6f1aSTakashi Iwai 	int err;
524538cf6f1aSTakashi Iwai 
524638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
524738cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
524838cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
5249352f7f91STakashi Iwai 					     hinfo);
5250e6b85f3cSTakashi Iwai 	if (!err) {
525138cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5252e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5253e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
5254e6b85f3cSTakashi Iwai 	}
525538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
525638cf6f1aSTakashi Iwai 	return err;
5257352f7f91STakashi Iwai }
5258352f7f91STakashi Iwai 
5259352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
526097ec558aSTakashi Iwai 				struct hda_codec *codec,
526197ec558aSTakashi Iwai 				unsigned int stream_tag,
526297ec558aSTakashi Iwai 				unsigned int format,
526397ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
526497ec558aSTakashi Iwai {
5265352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5266e6b85f3cSTakashi Iwai 	int err;
5267e6b85f3cSTakashi Iwai 
5268e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5269352f7f91STakashi Iwai 					       stream_tag, format, substream);
5270e6b85f3cSTakashi Iwai 	if (!err)
5271e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5272e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
5273e6b85f3cSTakashi Iwai 	return err;
5274352f7f91STakashi Iwai }
527597ec558aSTakashi Iwai 
5276352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5277352f7f91STakashi Iwai 				struct hda_codec *codec,
5278352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
5279352f7f91STakashi Iwai {
5280352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5281e6b85f3cSTakashi Iwai 	int err;
5282e6b85f3cSTakashi Iwai 
5283e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5284e6b85f3cSTakashi Iwai 	if (!err)
5285e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5286e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
5287e6b85f3cSTakashi Iwai 	return err;
5288352f7f91STakashi Iwai }
5289352f7f91STakashi Iwai 
529038cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
529138cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
529238cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
529338cf6f1aSTakashi Iwai {
529438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
529538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
529638cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5297e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5298e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
529938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
530038cf6f1aSTakashi Iwai 	return 0;
530138cf6f1aSTakashi Iwai }
530238cf6f1aSTakashi Iwai 
5303ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5304ac2e8736STakashi Iwai 			    struct hda_codec *codec,
5305ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
5306ac2e8736STakashi Iwai {
5307ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5308ac2e8736STakashi Iwai 	return 0;
5309ac2e8736STakashi Iwai }
5310ac2e8736STakashi Iwai 
5311ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5312ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5313ac2e8736STakashi Iwai 			       unsigned int stream_tag,
5314ac2e8736STakashi Iwai 			       unsigned int format,
5315ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5316ac2e8736STakashi Iwai {
5317ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5318ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5319ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
5320ac2e8736STakashi Iwai 	return 0;
5321ac2e8736STakashi Iwai }
5322ac2e8736STakashi Iwai 
5323ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5324ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5325ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5326ac2e8736STakashi Iwai {
5327ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5328ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5329ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
5330ac2e8736STakashi Iwai 	return 0;
5331ac2e8736STakashi Iwai }
5332ac2e8736STakashi Iwai 
5333ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5334ac2e8736STakashi Iwai 			     struct hda_codec *codec,
5335ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
5336ac2e8736STakashi Iwai {
5337ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5338ac2e8736STakashi Iwai 	return 0;
5339ac2e8736STakashi Iwai }
5340ac2e8736STakashi Iwai 
534138cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
534238cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
534338cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
534438cf6f1aSTakashi Iwai {
534538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
534638cf6f1aSTakashi Iwai 	int err = 0;
534738cf6f1aSTakashi Iwai 
534838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
5349d1f15e06STakashi Iwai 	if (spec->indep_hp && !spec->indep_hp_enabled)
535038cf6f1aSTakashi Iwai 		err = -EBUSY;
535138cf6f1aSTakashi Iwai 	else
535238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5353e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5354e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
535538cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
535638cf6f1aSTakashi Iwai 	return err;
535738cf6f1aSTakashi Iwai }
535838cf6f1aSTakashi Iwai 
535938cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
536038cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
536138cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
536238cf6f1aSTakashi Iwai {
536338cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
536438cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
536538cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5366e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5367e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
536838cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
536938cf6f1aSTakashi Iwai 	return 0;
537038cf6f1aSTakashi Iwai }
537138cf6f1aSTakashi Iwai 
5372e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5373e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5374e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
5375e6b85f3cSTakashi Iwai 				    unsigned int format,
5376e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5377e6b85f3cSTakashi Iwai {
5378e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5379e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5380e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
5381e6b85f3cSTakashi Iwai 	return 0;
5382e6b85f3cSTakashi Iwai }
5383e6b85f3cSTakashi Iwai 
5384e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5385e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5386e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5387e6b85f3cSTakashi Iwai {
5388e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5389e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5390e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
5391e6b85f3cSTakashi Iwai 	return 0;
5392e6b85f3cSTakashi Iwai }
5393e6b85f3cSTakashi Iwai 
5394352f7f91STakashi Iwai /*
5395352f7f91STakashi Iwai  * Digital out
5396352f7f91STakashi Iwai  */
5397352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5398352f7f91STakashi Iwai 				 struct hda_codec *codec,
5399352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
5400352f7f91STakashi Iwai {
5401352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5402352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5403352f7f91STakashi Iwai }
5404352f7f91STakashi Iwai 
5405352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5406352f7f91STakashi Iwai 				    struct hda_codec *codec,
5407352f7f91STakashi Iwai 				    unsigned int stream_tag,
5408352f7f91STakashi Iwai 				    unsigned int format,
5409352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5410352f7f91STakashi Iwai {
5411352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5412352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5413352f7f91STakashi Iwai 					     stream_tag, format, substream);
5414352f7f91STakashi Iwai }
5415352f7f91STakashi Iwai 
5416352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5417352f7f91STakashi Iwai 				    struct hda_codec *codec,
5418352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5419352f7f91STakashi Iwai {
5420352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5421352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5422352f7f91STakashi Iwai }
5423352f7f91STakashi Iwai 
5424352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5425352f7f91STakashi Iwai 				  struct hda_codec *codec,
5426352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
5427352f7f91STakashi Iwai {
5428352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5429352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5430352f7f91STakashi Iwai }
5431352f7f91STakashi Iwai 
5432352f7f91STakashi Iwai /*
5433352f7f91STakashi Iwai  * Analog capture
5434352f7f91STakashi Iwai  */
5435ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
5436ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
5437ac2e8736STakashi Iwai 
5438352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5439352f7f91STakashi Iwai 				   struct hda_codec *codec,
5440352f7f91STakashi Iwai 				   unsigned int stream_tag,
5441352f7f91STakashi Iwai 				   unsigned int format,
5442352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
5443352f7f91STakashi Iwai {
5444352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5445352f7f91STakashi Iwai 
5446352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
544797ec558aSTakashi Iwai 				   stream_tag, 0, format);
5448ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5449ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
545097ec558aSTakashi Iwai 	return 0;
545197ec558aSTakashi Iwai }
545297ec558aSTakashi Iwai 
5453352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
545497ec558aSTakashi Iwai 				   struct hda_codec *codec,
545597ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
545697ec558aSTakashi Iwai {
5457352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
545897ec558aSTakashi Iwai 
5459352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
5460352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
5461ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5462ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
546397ec558aSTakashi Iwai 	return 0;
546497ec558aSTakashi Iwai }
546597ec558aSTakashi Iwai 
5466352f7f91STakashi Iwai /*
5467352f7f91STakashi Iwai  */
5468352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
5469352f7f91STakashi Iwai 	.substreams = 1,
5470352f7f91STakashi Iwai 	.channels_min = 2,
5471352f7f91STakashi Iwai 	.channels_max = 8,
5472352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5473352f7f91STakashi Iwai 	.ops = {
5474352f7f91STakashi Iwai 		.open = playback_pcm_open,
547538cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
5476352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
5477352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
5478352f7f91STakashi Iwai 	},
5479352f7f91STakashi Iwai };
5480352f7f91STakashi Iwai 
5481352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
5482352f7f91STakashi Iwai 	.substreams = 1,
5483352f7f91STakashi Iwai 	.channels_min = 2,
5484352f7f91STakashi Iwai 	.channels_max = 2,
5485352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5486ac2e8736STakashi Iwai 	.ops = {
5487ac2e8736STakashi Iwai 		.open = capture_pcm_open,
5488ac2e8736STakashi Iwai 		.close = capture_pcm_close,
5489ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
5490ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
5491ac2e8736STakashi Iwai 	},
5492352f7f91STakashi Iwai };
5493352f7f91STakashi Iwai 
5494352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
5495352f7f91STakashi Iwai 	.substreams = 1,
5496352f7f91STakashi Iwai 	.channels_min = 2,
5497352f7f91STakashi Iwai 	.channels_max = 2,
5498352f7f91STakashi Iwai 	/* NID is set in build_pcms */
549938cf6f1aSTakashi Iwai 	.ops = {
550038cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
5501e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
5502e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
5503e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
550438cf6f1aSTakashi Iwai 	},
5505352f7f91STakashi Iwai };
5506352f7f91STakashi Iwai 
5507352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
5508352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
5509352f7f91STakashi Iwai 	.channels_min = 2,
5510352f7f91STakashi Iwai 	.channels_max = 2,
5511352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5512352f7f91STakashi Iwai 	.ops = {
5513ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5514ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5515352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5516352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5517352f7f91STakashi Iwai 	},
5518352f7f91STakashi Iwai };
5519352f7f91STakashi Iwai 
5520352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5521352f7f91STakashi Iwai 	.substreams = 1,
5522352f7f91STakashi Iwai 	.channels_min = 2,
5523352f7f91STakashi Iwai 	.channels_max = 2,
5524352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5525352f7f91STakashi Iwai 	.ops = {
5526352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5527352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5528352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5529352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5530352f7f91STakashi Iwai 	},
5531352f7f91STakashi Iwai };
5532352f7f91STakashi Iwai 
5533352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5534352f7f91STakashi Iwai 	.substreams = 1,
5535352f7f91STakashi Iwai 	.channels_min = 2,
5536352f7f91STakashi Iwai 	.channels_max = 2,
5537352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5538352f7f91STakashi Iwai };
5539352f7f91STakashi Iwai 
5540352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5541352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5542352f7f91STakashi Iwai 	.substreams = 0,
5543352f7f91STakashi Iwai 	.channels_min = 0,
5544352f7f91STakashi Iwai 	.channels_max = 0,
5545352f7f91STakashi Iwai };
5546352f7f91STakashi Iwai 
5547352f7f91STakashi Iwai /*
5548352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5549352f7f91STakashi Iwai  */
5550352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
55511da177e4SLinus Torvalds {
5552352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5553352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
55541da177e4SLinus Torvalds 
5555352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5556352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5557352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5558352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5559352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5560352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5561352f7f91STakashi Iwai 					   spec->cur_adc_format);
5562352f7f91STakashi Iwai 		return true;
5563352f7f91STakashi Iwai 	}
5564352f7f91STakashi Iwai 	return false;
5565352f7f91STakashi Iwai }
5566352f7f91STakashi Iwai 
5567352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5568352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5569352f7f91STakashi Iwai 				       struct hda_codec *codec,
5570352f7f91STakashi Iwai 				       unsigned int stream_tag,
5571352f7f91STakashi Iwai 				       unsigned int format,
5572352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5573352f7f91STakashi Iwai {
5574352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5575352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5576352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5577352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5578352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
55794f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
55801da177e4SLinus Torvalds 	return 0;
55811da177e4SLinus Torvalds }
55821da177e4SLinus Torvalds 
5583352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5584352f7f91STakashi Iwai 				       struct hda_codec *codec,
5585352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5586352f7f91STakashi Iwai {
5587352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5588352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5589352f7f91STakashi Iwai 	spec->cur_adc = 0;
55904f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
5591352f7f91STakashi Iwai 	return 0;
5592352f7f91STakashi Iwai }
5593352f7f91STakashi Iwai 
5594352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5595352f7f91STakashi Iwai 	.substreams = 1,
5596352f7f91STakashi Iwai 	.channels_min = 2,
5597352f7f91STakashi Iwai 	.channels_max = 2,
5598352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5599352f7f91STakashi Iwai 	.ops = {
5600352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5601352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5602352f7f91STakashi Iwai 	},
5603352f7f91STakashi Iwai };
5604352f7f91STakashi Iwai 
5605f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5606f873e536STakashi Iwai 				 const char *chip_name)
5607f873e536STakashi Iwai {
5608f873e536STakashi Iwai 	char *p;
5609f873e536STakashi Iwai 
5610f873e536STakashi Iwai 	if (*str)
5611f873e536STakashi Iwai 		return;
561275b1a8f9SJoe Perches 	strscpy(str, chip_name, len);
5613f873e536STakashi Iwai 
5614f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5615f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5616f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5617f873e536STakashi Iwai 			*p = 0;
5618f873e536STakashi Iwai 			break;
5619f873e536STakashi Iwai 		}
5620f873e536STakashi Iwai 	}
5621f873e536STakashi Iwai 	strlcat(str, sfx, len);
5622f873e536STakashi Iwai }
5623f873e536STakashi Iwai 
5624fb83b635STakashi Iwai /* copy PCM stream info from @default_str, and override non-NULL entries
5625fb83b635STakashi Iwai  * from @spec_str and @nid
5626fb83b635STakashi Iwai  */
5627fb83b635STakashi Iwai static void setup_pcm_stream(struct hda_pcm_stream *str,
5628fb83b635STakashi Iwai 			     const struct hda_pcm_stream *default_str,
5629fb83b635STakashi Iwai 			     const struct hda_pcm_stream *spec_str,
5630fb83b635STakashi Iwai 			     hda_nid_t nid)
5631fb83b635STakashi Iwai {
5632fb83b635STakashi Iwai 	*str = *default_str;
5633fb83b635STakashi Iwai 	if (nid)
5634fb83b635STakashi Iwai 		str->nid = nid;
5635fb83b635STakashi Iwai 	if (spec_str) {
5636fb83b635STakashi Iwai 		if (spec_str->substreams)
5637fb83b635STakashi Iwai 			str->substreams = spec_str->substreams;
5638fb83b635STakashi Iwai 		if (spec_str->channels_min)
5639fb83b635STakashi Iwai 			str->channels_min = spec_str->channels_min;
5640fb83b635STakashi Iwai 		if (spec_str->channels_max)
5641fb83b635STakashi Iwai 			str->channels_max = spec_str->channels_max;
5642fb83b635STakashi Iwai 		if (spec_str->rates)
5643fb83b635STakashi Iwai 			str->rates = spec_str->rates;
5644fb83b635STakashi Iwai 		if (spec_str->formats)
5645fb83b635STakashi Iwai 			str->formats = spec_str->formats;
5646fb83b635STakashi Iwai 		if (spec_str->maxbps)
5647fb83b635STakashi Iwai 			str->maxbps = spec_str->maxbps;
5648fb83b635STakashi Iwai 	}
5649fb83b635STakashi Iwai }
5650fb83b635STakashi Iwai 
5651dda42bd0STakashi Iwai /**
5652dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5653dda42bd0STakashi Iwai  * @codec: the HDA codec
5654dda42bd0STakashi Iwai  *
5655dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5656dda42bd0STakashi Iwai  */
5657352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5658352f7f91STakashi Iwai {
5659352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5660bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5661352f7f91STakashi Iwai 	bool have_multi_adcs;
5662352f7f91STakashi Iwai 
5663352f7f91STakashi Iwai 	if (spec->no_analog)
5664352f7f91STakashi Iwai 		goto skip_analog;
5665352f7f91STakashi Iwai 
5666f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5667f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
56687639a06cSTakashi Iwai 			     " Analog", codec->core.chip_name);
5669bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5670bbbc7e85STakashi Iwai 	if (!info)
5671bbbc7e85STakashi Iwai 		return -ENOMEM;
5672bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5673352f7f91STakashi Iwai 
5674352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5675fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5676fb83b635STakashi Iwai 				 &pcm_analog_playback,
5677fb83b635STakashi Iwai 				 spec->stream_analog_playback,
5678fb83b635STakashi Iwai 				 spec->multiout.dac_nids[0]);
5679352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5680352f7f91STakashi Iwai 			spec->multiout.max_channels;
5681352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5682352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5683352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5684352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5685352f7f91STakashi Iwai 	}
5686352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5687fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5688fb83b635STakashi Iwai 				 (spec->dyn_adc_switch ?
5689fb83b635STakashi Iwai 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5690fb83b635STakashi Iwai 				 spec->stream_analog_capture,
5691fb83b635STakashi Iwai 				 spec->adc_nids[0]);
5692352f7f91STakashi Iwai 	}
5693352f7f91STakashi Iwai 
5694352f7f91STakashi Iwai  skip_analog:
5695352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5696352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5697f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5698352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
56997639a06cSTakashi Iwai 				     " Digital", codec->core.chip_name);
5700bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5701bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5702bbbc7e85STakashi Iwai 		if (!info)
5703bbbc7e85STakashi Iwai 			return -ENOMEM;
57049ab0cb30STakashi Iwai 		codec->follower_dig_outs = spec->multiout.follower_dig_outs;
5705bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5706352f7f91STakashi Iwai 		if (spec->dig_out_type)
5707352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5708352f7f91STakashi Iwai 		else
5709352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5710fb83b635STakashi Iwai 		if (spec->multiout.dig_out_nid)
5711fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5712fb83b635STakashi Iwai 					 &pcm_digital_playback,
5713fb83b635STakashi Iwai 					 spec->stream_digital_playback,
5714fb83b635STakashi Iwai 					 spec->multiout.dig_out_nid);
5715fb83b635STakashi Iwai 		if (spec->dig_in_nid)
5716fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5717fb83b635STakashi Iwai 					 &pcm_digital_capture,
5718fb83b635STakashi Iwai 					 spec->stream_digital_capture,
5719fb83b635STakashi Iwai 					 spec->dig_in_nid);
5720352f7f91STakashi Iwai 	}
5721352f7f91STakashi Iwai 
5722352f7f91STakashi Iwai 	if (spec->no_analog)
5723352f7f91STakashi Iwai 		return 0;
5724352f7f91STakashi Iwai 
5725352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5726352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5727352f7f91STakashi Iwai 	 */
5728352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5729352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5730352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5731352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5732a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5733a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
57347639a06cSTakashi Iwai 			     " Alt Analog", codec->core.chip_name);
5735bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5736bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5737bbbc7e85STakashi Iwai 		if (!info)
5738bbbc7e85STakashi Iwai 			return -ENOMEM;
5739bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5740fb83b635STakashi Iwai 		if (spec->alt_dac_nid)
5741fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5742fb83b635STakashi Iwai 					 &pcm_analog_alt_playback,
5743fb83b635STakashi Iwai 					 spec->stream_analog_alt_playback,
5744fb83b635STakashi Iwai 					 spec->alt_dac_nid);
5745fb83b635STakashi Iwai 		else
5746fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5747fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5748352f7f91STakashi Iwai 		if (have_multi_adcs) {
5749fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5750fb83b635STakashi Iwai 					 &pcm_analog_alt_capture,
5751fb83b635STakashi Iwai 					 spec->stream_analog_alt_capture,
5752fb83b635STakashi Iwai 					 spec->adc_nids[1]);
5753352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5754352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5755352f7f91STakashi Iwai 		} else {
5756fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5757fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5758352f7f91STakashi Iwai 		}
57591da177e4SLinus Torvalds 	}
57601da177e4SLinus Torvalds 
57611da177e4SLinus Torvalds 	return 0;
57621da177e4SLinus Torvalds }
57632698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5764352f7f91STakashi Iwai 
5765352f7f91STakashi Iwai 
5766352f7f91STakashi Iwai /*
5767352f7f91STakashi Iwai  * Standard auto-parser initializations
5768352f7f91STakashi Iwai  */
5769352f7f91STakashi Iwai 
5770d4156930STakashi Iwai /* configure the given path as a proper output */
57712c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5772352f7f91STakashi Iwai {
5773352f7f91STakashi Iwai 	struct nid_path *path;
5774d4156930STakashi Iwai 	hda_nid_t pin;
5775352f7f91STakashi Iwai 
5776196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5777d4156930STakashi Iwai 	if (!path || !path->depth)
5778352f7f91STakashi Iwai 		return;
5779d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
57802c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
578165033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
578265033cc8STakashi Iwai 			      aamix_default(codec->spec));
5783e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5784352f7f91STakashi Iwai }
5785352f7f91STakashi Iwai 
5786352f7f91STakashi Iwai /* initialize primary output paths */
5787352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5788352f7f91STakashi Iwai {
5789352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5790352f7f91STakashi Iwai 	int i;
5791352f7f91STakashi Iwai 
5792d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
57932c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5794352f7f91STakashi Iwai }
5795352f7f91STakashi Iwai 
5796db23fd19STakashi Iwai 
57972c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5798352f7f91STakashi Iwai {
5799352f7f91STakashi Iwai 	int i;
5800352f7f91STakashi Iwai 
5801d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
58022c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5803352f7f91STakashi Iwai }
5804db23fd19STakashi Iwai 
5805db23fd19STakashi Iwai /* initialize hp and speaker paths */
5806db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5807db23fd19STakashi Iwai {
5808db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5809db23fd19STakashi Iwai 
5810db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
58112c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5812db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5813db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
58142c12c30dSTakashi Iwai 				 spec->speaker_paths);
5815352f7f91STakashi Iwai }
5816352f7f91STakashi Iwai 
5817352f7f91STakashi Iwai /* initialize multi-io paths */
5818352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5819352f7f91STakashi Iwai {
5820352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5821352f7f91STakashi Iwai 	int i;
5822352f7f91STakashi Iwai 
5823352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5824352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5825352f7f91STakashi Iwai 		struct nid_path *path;
5826196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5827352f7f91STakashi Iwai 		if (!path)
5828352f7f91STakashi Iwai 			continue;
5829352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5830352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
58312c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
583265033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
583365033cc8STakashi Iwai 				      aamix_default(spec));
5834352f7f91STakashi Iwai 	}
5835352f7f91STakashi Iwai }
5836352f7f91STakashi Iwai 
58374f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
58384f7f67fbSTakashi Iwai {
58394f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
58404f7f67fbSTakashi Iwai 
58414f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
58424f7f67fbSTakashi Iwai 		return;
5843e7fdd527STakashi Iwai 	if (!has_aamix_out_paths(spec))
5844e7fdd527STakashi Iwai 		return;
58454f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
58464f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
58474f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
58484f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
58494f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
58504f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
58514f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
58524f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
58534f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
58544f7f67fbSTakashi Iwai }
58554f7f67fbSTakashi Iwai 
5856352f7f91STakashi Iwai /* set up input pins and loopback paths */
5857352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5858352f7f91STakashi Iwai {
5859352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5860352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5861352f7f91STakashi Iwai 	int i;
5862352f7f91STakashi Iwai 
5863352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5864352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5865352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
58662c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5867352f7f91STakashi Iwai 
5868352f7f91STakashi Iwai 		/* init loopback inputs */
5869352f7f91STakashi Iwai 		if (spec->mixer_nid) {
58703e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
58713e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5872352f7f91STakashi Iwai 		}
5873352f7f91STakashi Iwai 	}
5874352f7f91STakashi Iwai }
5875352f7f91STakashi Iwai 
5876352f7f91STakashi Iwai /* initialize ADC paths */
5877352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5878352f7f91STakashi Iwai {
5879352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5880352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5881352f7f91STakashi Iwai 	struct nid_path *path;
5882352f7f91STakashi Iwai 	int i, c, nums;
5883352f7f91STakashi Iwai 
5884352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5885352f7f91STakashi Iwai 		nums = 1;
5886352f7f91STakashi Iwai 	else
5887352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5888352f7f91STakashi Iwai 
5889352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5890352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5891c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5892352f7f91STakashi Iwai 			if (path) {
5893352f7f91STakashi Iwai 				bool active = path->active;
5894352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5895352f7f91STakashi Iwai 					active = true;
5896352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5897352f7f91STakashi Iwai 			}
5898352f7f91STakashi Iwai 		}
5899967303daSTakashi Iwai 		if (spec->hp_mic)
5900967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5901352f7f91STakashi Iwai 	}
5902352f7f91STakashi Iwai 
5903352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
59047fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
5905352f7f91STakashi Iwai }
5906352f7f91STakashi Iwai 
5907352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5908352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
5909352f7f91STakashi Iwai {
5910352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5911352f7f91STakashi Iwai 	int i;
5912352f7f91STakashi Iwai 	hda_nid_t pin;
5913352f7f91STakashi Iwai 
5914d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
59152c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
5916352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
59172430d7b7STakashi Iwai 	if (pin) {
59182c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
59193e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
59202430d7b7STakashi Iwai 	}
5921352f7f91STakashi Iwai }
5922352f7f91STakashi Iwai 
5923973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
5924973e4972STakashi Iwai  * invalid unsol tags by some reason
5925973e4972STakashi Iwai  */
5926973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
5927973e4972STakashi Iwai {
5928a9c2dfc8STakashi Iwai 	const struct hda_pincfg *pin;
5929973e4972STakashi Iwai 	int i;
5930973e4972STakashi Iwai 
5931a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->init_pins, i, pin) {
5932973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
5933973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
5934973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
5935401caff7STakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
5936973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
5937973e4972STakashi Iwai 	}
5938973e4972STakashi Iwai }
5939973e4972STakashi Iwai 
5940dda42bd0STakashi Iwai /**
5941dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
5942dda42bd0STakashi Iwai  * @codec: the HDA codec
5943dda42bd0STakashi Iwai  *
5944dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
59455187ac16STakashi Iwai  */
5946352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
5947352f7f91STakashi Iwai {
5948352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5949352f7f91STakashi Iwai 
5950352f7f91STakashi Iwai 	if (spec->init_hook)
5951352f7f91STakashi Iwai 		spec->init_hook(codec);
5952352f7f91STakashi Iwai 
595389781d08STakashi Iwai 	if (!spec->skip_verbs)
5954352f7f91STakashi Iwai 		snd_hda_apply_verbs(codec);
5955352f7f91STakashi Iwai 
5956352f7f91STakashi Iwai 	init_multi_out(codec);
5957352f7f91STakashi Iwai 	init_extra_out(codec);
5958352f7f91STakashi Iwai 	init_multi_io(codec);
59594f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
5960352f7f91STakashi Iwai 	init_analog_input(codec);
5961352f7f91STakashi Iwai 	init_input_src(codec);
5962352f7f91STakashi Iwai 	init_digital(codec);
5963352f7f91STakashi Iwai 
5964973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
5965973e4972STakashi Iwai 
5966e6feb5d0STakashi Iwai 	sync_all_pin_power_ctls(codec);
5967e6feb5d0STakashi Iwai 
5968352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
5969a5cc2509STakashi Iwai 	update_automute_all(codec);
5970352f7f91STakashi Iwai 
59711a462be5STakashi Iwai 	snd_hda_regmap_sync(codec);
59723bbcd274STakashi Iwai 
5973352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
5974352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5975352f7f91STakashi Iwai 
5976352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
5977352f7f91STakashi Iwai 	return 0;
5978352f7f91STakashi Iwai }
59792698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
5980fce52a3bSTakashi Iwai 
5981dda42bd0STakashi Iwai /**
5982dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
5983dda42bd0STakashi Iwai  * @codec: the HDA codec
5984dda42bd0STakashi Iwai  *
5985dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
59865187ac16STakashi Iwai  */
5987fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
5988fce52a3bSTakashi Iwai {
59898a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
5990fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
5991fce52a3bSTakashi Iwai 	kfree(codec->spec);
5992fce52a3bSTakashi Iwai 	codec->spec = NULL;
5993fce52a3bSTakashi Iwai }
59942698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
5995fce52a3bSTakashi Iwai 
5996871b9066SHui Wang /**
5997871b9066SHui Wang  * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
5998871b9066SHui Wang  * @codec: the HDA codec
5999871b9066SHui Wang  *
6000871b9066SHui Wang  * This can be put as patch_ops reboot_notify function.
6001871b9066SHui Wang  */
6002871b9066SHui Wang void snd_hda_gen_reboot_notify(struct hda_codec *codec)
6003871b9066SHui Wang {
6004871b9066SHui Wang 	/* Make the codec enter D3 to avoid spurious noises from the internal
6005871b9066SHui Wang 	 * speaker during (and after) reboot
6006871b9066SHui Wang 	 */
6007871b9066SHui Wang 	snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
6008871b9066SHui Wang 	snd_hda_codec_write(codec, codec->core.afg, 0,
6009871b9066SHui Wang 			    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
6010871b9066SHui Wang 	msleep(10);
6011871b9066SHui Wang }
6012871b9066SHui Wang EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
6013871b9066SHui Wang 
6014fce52a3bSTakashi Iwai #ifdef CONFIG_PM
6015dda42bd0STakashi Iwai /**
6016dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
6017dda42bd0STakashi Iwai  * @codec: the HDA codec
6018dda42bd0STakashi Iwai  * @nid: NID to inspect
6019dda42bd0STakashi Iwai  *
6020dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
60215187ac16STakashi Iwai  */
6022fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
6023fce52a3bSTakashi Iwai {
6024fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6025fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
6026fce52a3bSTakashi Iwai }
60272698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
6028fce52a3bSTakashi Iwai #endif
6029352f7f91STakashi Iwai 
6030352f7f91STakashi Iwai 
6031352f7f91STakashi Iwai /*
6032352f7f91STakashi Iwai  * the generic codec support
6033352f7f91STakashi Iwai  */
60341da177e4SLinus Torvalds 
6035352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
6036352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
6037352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
6038352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
6039fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
6040352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
6041871b9066SHui Wang 	.reboot_notify = snd_hda_gen_reboot_notify,
604283012a7cSTakashi Iwai #ifdef CONFIG_PM
6043fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
6044cb53c626STakashi Iwai #endif
60451da177e4SLinus Torvalds };
60461da177e4SLinus Torvalds 
6047d8a766a1STakashi Iwai /*
6048dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
6049dda42bd0STakashi Iwai  * @codec: the HDA codec
6050dda42bd0STakashi Iwai  */
6051d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
60521da177e4SLinus Torvalds {
6053352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
60541da177e4SLinus Torvalds 	int err;
60551da177e4SLinus Torvalds 
6056e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6057352f7f91STakashi Iwai 	if (!spec)
60581da177e4SLinus Torvalds 		return -ENOMEM;
6059352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
60601da177e4SLinus Torvalds 	codec->spec = spec;
60611da177e4SLinus Torvalds 
60629eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
60639eb413e5STakashi Iwai 	if (err < 0)
6064cfef67f0SWenwen Wang 		goto error;
60659eb413e5STakashi Iwai 
60669eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
6067352f7f91STakashi Iwai 	if (err < 0)
60681da177e4SLinus Torvalds 		goto error;
60691da177e4SLinus Torvalds 
60701da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
60711da177e4SLinus Torvalds 	return 0;
60721da177e4SLinus Torvalds 
60731da177e4SLinus Torvalds error:
6074fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
60751da177e4SLinus Torvalds 	return err;
60761da177e4SLinus Torvalds }
6077d8a766a1STakashi Iwai 
6078b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_generic[] = {
6079b9a94a9cSTakashi Iwai 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
6080d8a766a1STakashi Iwai 	{} /* terminator */
6081d8a766a1STakashi Iwai };
6082b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
6083d8a766a1STakashi Iwai 
6084d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
6085b9a94a9cSTakashi Iwai 	.id = snd_hda_id_generic,
6086d8a766a1STakashi Iwai };
6087d8a766a1STakashi Iwai 
6088d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
6089b21bdd0dSTakashi Iwai 
6090b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
6091b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
6092