xref: /openbmc/linux/sound/pci/hda/hda_generic.c (revision 242d990c)
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;
984352f7f91STakashi Iwai 	knew->private_value = val;
985a35bd1e3STakashi Iwai 	return knew;
986352f7f91STakashi Iwai }
987352f7f91STakashi Iwai 
988352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
989352f7f91STakashi Iwai 				const char *pfx, const char *dir,
990352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
991352f7f91STakashi Iwai {
992975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
993352f7f91STakashi Iwai 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
994a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
995a35bd1e3STakashi Iwai 		return -ENOMEM;
996a35bd1e3STakashi Iwai 	return 0;
997352f7f91STakashi Iwai }
998352f7f91STakashi Iwai 
999352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1000352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1001352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1002352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1003352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1004352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1005352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1006352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1007352f7f91STakashi Iwai 
1008352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1009352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
1010352f7f91STakashi Iwai {
1011352f7f91STakashi Iwai 	unsigned int val;
1012352f7f91STakashi Iwai 	if (!path)
1013352f7f91STakashi Iwai 		return 0;
1014352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
1015352f7f91STakashi Iwai 	if (!val)
1016352f7f91STakashi Iwai 		return 0;
1017352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1018352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1019352f7f91STakashi Iwai }
1020352f7f91STakashi Iwai 
1021352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
1022352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1023352f7f91STakashi Iwai 			       int type)
1024352f7f91STakashi Iwai {
1025352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
1026352f7f91STakashi Iwai 	if (path) {
1027352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1028352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1029352f7f91STakashi Iwai 			chs = 3; /* stereo */
1030352f7f91STakashi Iwai 	}
1031352f7f91STakashi Iwai 	return chs;
1032352f7f91STakashi Iwai }
1033352f7f91STakashi Iwai 
1034352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1035352f7f91STakashi Iwai 			  struct nid_path *path)
1036352f7f91STakashi Iwai {
1037352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1038352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1039352f7f91STakashi Iwai }
1040352f7f91STakashi Iwai 
1041352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
1042352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1043352f7f91STakashi Iwai  */
1044352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1045352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
1046352f7f91STakashi Iwai {
1047352f7f91STakashi Iwai 	unsigned int val;
1048352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
1049352f7f91STakashi Iwai 
1050352f7f91STakashi Iwai 	if (!path)
1051352f7f91STakashi Iwai 		return 0;
1052352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
1053352f7f91STakashi Iwai 	if (!val)
1054352f7f91STakashi Iwai 		return 0;
1055352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1056352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
1057352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
1058352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
1059352f7f91STakashi Iwai 		if (nums > 1) {
1060352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
1061352f7f91STakashi Iwai 			val |= nums << 19;
1062352f7f91STakashi Iwai 		}
1063352f7f91STakashi Iwai 	}
1064352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1065352f7f91STakashi Iwai }
1066352f7f91STakashi Iwai 
1067352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1068352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1069352f7f91STakashi Iwai {
1070352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1071352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1072352f7f91STakashi Iwai }
1073352f7f91STakashi Iwai 
10747eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1075bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10767eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10777eebffd3STakashi Iwai {
10787eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10797eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10807eebffd3STakashi Iwai 
10817eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10827eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10837eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10847eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10857eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10867eebffd3STakashi Iwai 	}
1087bc2eee29STakashi Iwai }
10887eebffd3STakashi Iwai 
1089bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1090bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1091bc2eee29STakashi Iwai {
1092bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
10937eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
10947eebffd3STakashi Iwai }
10957eebffd3STakashi Iwai 
1096698f5ee3STakashi Iwai /*
1097698f5ee3STakashi Iwai  * Bound mute controls
1098698f5ee3STakashi Iwai  */
1099698f5ee3STakashi Iwai #define AMP_VAL_IDX_SHIFT	19
1100698f5ee3STakashi Iwai #define AMP_VAL_IDX_MASK	(0x0f<<19)
1101698f5ee3STakashi Iwai 
1102698f5ee3STakashi Iwai static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
1103698f5ee3STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1104698f5ee3STakashi Iwai {
1105698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1106698f5ee3STakashi Iwai 	unsigned long pval;
1107698f5ee3STakashi Iwai 	int err;
1108698f5ee3STakashi Iwai 
1109698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1110698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1111698f5ee3STakashi Iwai 	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1112698f5ee3STakashi Iwai 	err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1113698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1114698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1115698f5ee3STakashi Iwai 	return err;
1116698f5ee3STakashi Iwai }
1117698f5ee3STakashi Iwai 
1118bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1119bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1120bc2eee29STakashi Iwai {
1121698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1122698f5ee3STakashi Iwai 	unsigned long pval;
1123698f5ee3STakashi Iwai 	int i, indices, err = 0, change = 0;
1124698f5ee3STakashi Iwai 
1125bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1126698f5ee3STakashi Iwai 
1127698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1128698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1129698f5ee3STakashi Iwai 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1130698f5ee3STakashi Iwai 	for (i = 0; i < indices; i++) {
1131698f5ee3STakashi Iwai 		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1132698f5ee3STakashi Iwai 			(i << AMP_VAL_IDX_SHIFT);
1133698f5ee3STakashi Iwai 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1134698f5ee3STakashi Iwai 		if (err < 0)
1135698f5ee3STakashi Iwai 			break;
1136698f5ee3STakashi Iwai 		change |= err;
1137698f5ee3STakashi Iwai 	}
1138698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1139698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1140698f5ee3STakashi Iwai 	return err < 0 ? err : change;
1141bc2eee29STakashi Iwai }
1142bc2eee29STakashi Iwai 
1143247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1144247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1145247d85eeSTakashi Iwai {
1146247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1147247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1148247d85eeSTakashi Iwai }
1149247d85eeSTakashi Iwai 
1150352f7f91STakashi Iwai static const char * const channel_name[4] = {
1151352f7f91STakashi Iwai 	"Front", "Surround", "CLFE", "Side"
1152352f7f91STakashi Iwai };
1153352f7f91STakashi Iwai 
1154352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1155247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1156247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1157352f7f91STakashi Iwai {
1158247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1159352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1160352f7f91STakashi Iwai 
1161352f7f91STakashi Iwai 	*index = 0;
1162352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
11639f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1164247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1165352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1166352f7f91STakashi Iwai 
1167352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1168352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1169352f7f91STakashi Iwai 	 */
1170352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
11719f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1172352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1173352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1174352f7f91STakashi Iwai 
1175247d85eeSTakashi Iwai 	/* multi-io channels */
1176247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
1177247d85eeSTakashi Iwai 		return channel_name[ch];
1178247d85eeSTakashi Iwai 
1179352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1180352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1181247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1182247d85eeSTakashi Iwai 		 * don't name it as Speaker
1183247d85eeSTakashi Iwai 		 */
1184247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1185247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1186247d85eeSTakashi Iwai 			break;
1187352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1188352f7f91STakashi Iwai 			return "Speaker";
1189352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1190352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1191352f7f91STakashi Iwai 		break;
1192352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1193247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1194247d85eeSTakashi Iwai 		 * don't name it as Headphone
1195247d85eeSTakashi Iwai 		 */
1196247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1197247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1198247d85eeSTakashi Iwai 			break;
1199352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1200352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1201352f7f91STakashi Iwai 			break;
1202352f7f91STakashi Iwai 		*index = ch;
1203352f7f91STakashi Iwai 		return "Headphone";
120403ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
120503ad6a8cSDavid Henningsson 		/* This deals with the case where we have two DACs and
120603ad6a8cSDavid Henningsson 		 * one LO, one HP and one Speaker */
120703ad6a8cSDavid Henningsson 		if (!ch && cfg->speaker_outs && cfg->hp_outs) {
120803ad6a8cSDavid Henningsson 			bool hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
120903ad6a8cSDavid Henningsson 			bool spk_lo_shared = !path_has_mixer(codec, spec->speaker_paths[0], ctl_type);
121003ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
121103ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
121203ad6a8cSDavid Henningsson 			if (hp_lo_shared)
121303ad6a8cSDavid Henningsson 				return "Headphone+LO";
121403ad6a8cSDavid Henningsson 			if (spk_lo_shared)
121503ad6a8cSDavid Henningsson 				return "Speaker+LO";
121603ad6a8cSDavid Henningsson 		}
1217247d85eeSTakashi Iwai 	}
1218247d85eeSTakashi Iwai 
1219247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1220352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
12213abb4f4dSDavid Henningsson 		return "Line Out";
1222247d85eeSTakashi Iwai 
1223352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1224352f7f91STakashi Iwai 		snd_BUG();
1225352f7f91STakashi Iwai 		return "PCM";
1226352f7f91STakashi Iwai 	}
1227352f7f91STakashi Iwai 
1228352f7f91STakashi Iwai 	return channel_name[ch];
1229352f7f91STakashi Iwai }
1230352f7f91STakashi Iwai 
1231352f7f91STakashi Iwai /*
1232352f7f91STakashi Iwai  * Parse output paths
1233352f7f91STakashi Iwai  */
1234352f7f91STakashi Iwai 
1235352f7f91STakashi Iwai /* badness definition */
1236352f7f91STakashi Iwai enum {
1237352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1238352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1239352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1240352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1241352f7f91STakashi Iwai 	/* No possible multi-ios */
12421d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1243352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1244352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1245352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1246352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1247352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1248352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
124955a63d4dSTakashi Iwai 	/* No independent HP possible */
1250bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1251352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1252352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1253352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1254352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1255352f7f91STakashi Iwai 	/* Volume widget is shared */
1256352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1257352f7f91STakashi Iwai };
1258352f7f91STakashi Iwai 
12590e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1260352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1261352f7f91STakashi Iwai  *
1262352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1263352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1264352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1265352f7f91STakashi Iwai  */
12660e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1267352f7f91STakashi Iwai {
1268d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1269352f7f91STakashi Iwai 	hda_nid_t nid;
1270352f7f91STakashi Iwai 	unsigned int val;
1271352f7f91STakashi Iwai 	int badness = 0;
1272352f7f91STakashi Iwai 
1273352f7f91STakashi Iwai 	if (!path)
1274352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
12750e614dd0STakashi Iwai 
12760e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
12770e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
12780e614dd0STakashi Iwai 		return 0; /* already evaluated */
12790e614dd0STakashi Iwai 
1280352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1281352f7f91STakashi Iwai 	if (nid) {
1282352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1283d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1284d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1285352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1286352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1287352f7f91STakashi Iwai 		else
1288352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1289352f7f91STakashi Iwai 	} else
1290352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1291352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1292352f7f91STakashi Iwai 	if (nid) {
1293352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1294352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1295352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1296352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1297352f7f91STakashi Iwai 		else
1298352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1299352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1300352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1301352f7f91STakashi Iwai 		else
1302352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1303352f7f91STakashi Iwai 	} else
1304352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1305352f7f91STakashi Iwai 	return badness;
1306352f7f91STakashi Iwai }
1307352f7f91STakashi Iwai 
130898bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1309352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1310352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1311352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1312352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1313352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1314352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1315352f7f91STakashi Iwai };
13162698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1317352f7f91STakashi Iwai 
131898bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1319352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1320352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1321352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1322352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1323352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1324352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1325352f7f91STakashi Iwai };
13262698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1327352f7f91STakashi Iwai 
13287385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
13297385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
13307385df61STakashi Iwai {
13317385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
13327385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
13337385df61STakashi Iwai 
13347385df61STakashi Iwai 	if (cfg->line_outs > idx)
13357385df61STakashi Iwai 		return spec->private_dac_nids[idx];
13367385df61STakashi Iwai 	idx -= cfg->line_outs;
13377385df61STakashi Iwai 	if (spec->multi_ios > idx)
13387385df61STakashi Iwai 		return spec->multi_io[idx].dac;
13397385df61STakashi Iwai 	return 0;
13407385df61STakashi Iwai }
13417385df61STakashi Iwai 
13427385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
13437385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
13447385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
13457385df61STakashi Iwai {
13467385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
13477385df61STakashi Iwai }
13487385df61STakashi Iwai 
1349352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1350352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1351352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1352196c1766STakashi Iwai 			   int *path_idx,
1353352f7f91STakashi Iwai 			   const struct badness_table *bad)
1354352f7f91STakashi Iwai {
1355352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1356352f7f91STakashi Iwai 	int i, j;
1357352f7f91STakashi Iwai 	int badness = 0;
1358352f7f91STakashi Iwai 	hda_nid_t dac;
1359352f7f91STakashi Iwai 
1360352f7f91STakashi Iwai 	if (!num_outs)
1361352f7f91STakashi Iwai 		return 0;
1362352f7f91STakashi Iwai 
1363352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
13640c8c0f56STakashi Iwai 		struct nid_path *path;
1365352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
13661e0b5286STakashi Iwai 
1367242d990cSTakashi Iwai 		if (!spec->obey_preferred_dacs) {
13680e614dd0STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, path_idx[i]);
13690e614dd0STakashi Iwai 			if (path) {
13700e614dd0STakashi Iwai 				badness += assign_out_path_ctls(codec, path);
13711e0b5286STakashi Iwai 				continue;
13721e0b5286STakashi Iwai 			}
1373242d990cSTakashi Iwai 		}
13741e0b5286STakashi Iwai 
13753690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
13763690739bSTakashi Iwai 		if (dacs[i]) {
13773690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
13783690739bSTakashi Iwai 				badness += bad->shared_primary;
1379242d990cSTakashi Iwai 		} else if (spec->obey_preferred_dacs) {
1380242d990cSTakashi Iwai 			badness += BAD_NO_PRIMARY_DAC;
13813690739bSTakashi Iwai 		}
13823690739bSTakashi Iwai 
13833690739bSTakashi Iwai 		if (!dacs[i])
1384352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1385352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1386980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1387352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1388352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1389352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1390352f7f91STakashi Iwai 					dacs[j] = 0;
1391980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1392196c1766STakashi Iwai 					path_idx[j] = 0;
1393352f7f91STakashi Iwai 					break;
1394352f7f91STakashi Iwai 				}
1395352f7f91STakashi Iwai 			}
1396352f7f91STakashi Iwai 		}
1397352f7f91STakashi Iwai 		dac = dacs[i];
1398352f7f91STakashi Iwai 		if (!dac) {
13997385df61STakashi Iwai 			if (num_outs > 2)
14007385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
14017385df61STakashi Iwai 			if (!dac)
14027385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
14037385df61STakashi Iwai 			if (!dac)
14047385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1405352f7f91STakashi Iwai 			if (dac) {
1406352f7f91STakashi Iwai 				if (!i)
1407352f7f91STakashi Iwai 					badness += bad->shared_primary;
1408352f7f91STakashi Iwai 				else if (i == 1)
1409352f7f91STakashi Iwai 					badness += bad->shared_surr;
1410352f7f91STakashi Iwai 				else
1411352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1412352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1413352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1414352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1415352f7f91STakashi Iwai 			} else if (!i)
1416352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1417352f7f91STakashi Iwai 			else
1418352f7f91STakashi Iwai 				badness += bad->no_dac;
1419352f7f91STakashi Iwai 		}
14201fa335b0STakashi Iwai 		if (!dac)
14211fa335b0STakashi Iwai 			continue;
14223ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1423117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1424b3a8c745STakashi Iwai 			/* try with aamix */
14253ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1426b3a8c745STakashi Iwai 		}
14271fa335b0STakashi Iwai 		if (!path) {
1428352f7f91STakashi Iwai 			dac = dacs[i] = 0;
14291fa335b0STakashi Iwai 			badness += bad->no_dac;
14301fa335b0STakashi Iwai 		} else {
14314e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1432e1284af7STakashi Iwai 			path->active = true;
1433196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
14340e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1435e1284af7STakashi Iwai 		}
1436352f7f91STakashi Iwai 	}
1437352f7f91STakashi Iwai 
1438352f7f91STakashi Iwai 	return badness;
1439352f7f91STakashi Iwai }
1440352f7f91STakashi Iwai 
1441352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1442352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1443352f7f91STakashi Iwai {
1444352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1445352f7f91STakashi Iwai 	int i;
1446352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1447352f7f91STakashi Iwai 
1448352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1449352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1450352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1451352f7f91STakashi Iwai 			continue;
1452352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1453352f7f91STakashi Iwai 			if (nid_found)
1454352f7f91STakashi Iwai 				return 0;
1455352f7f91STakashi Iwai 			nid_found = nid;
1456352f7f91STakashi Iwai 		}
1457352f7f91STakashi Iwai 	}
1458352f7f91STakashi Iwai 	return nid_found;
1459352f7f91STakashi Iwai }
1460352f7f91STakashi Iwai 
1461352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1462352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1463352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1464352f7f91STakashi Iwai {
1465352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1466352f7f91STakashi Iwai 
1467352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1468352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1469352f7f91STakashi Iwai 		return false;
1470352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1471352f7f91STakashi Iwai 		return false;
1472352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1473352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1474352f7f91STakashi Iwai 		return false;
1475352f7f91STakashi Iwai 	return true;
1476352f7f91STakashi Iwai }
1477352f7f91STakashi Iwai 
1478e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1479e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1480e22aab7dSTakashi Iwai {
1481e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1482e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1483e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1484e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1485e22aab7dSTakashi Iwai 	int type, i;
1486e22aab7dSTakashi Iwai 	int num_pins = 0;
1487e22aab7dSTakashi Iwai 
1488e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1489e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1490e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1491e22aab7dSTakashi Iwai 				continue;
1492e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1493e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1494e22aab7dSTakashi Iwai 				num_pins++;
1495e22aab7dSTakashi Iwai 		}
1496e22aab7dSTakashi Iwai 	}
1497e22aab7dSTakashi Iwai 	return num_pins;
1498e22aab7dSTakashi Iwai }
1499e22aab7dSTakashi Iwai 
1500352f7f91STakashi Iwai /*
1501352f7f91STakashi Iwai  * multi-io helper
1502352f7f91STakashi Iwai  *
1503352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1504352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1505352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1506352f7f91STakashi Iwai  * the badness value.
1507352f7f91STakashi Iwai  */
1508352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1509352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1510e22aab7dSTakashi Iwai 			  bool hardwired)
1511352f7f91STakashi Iwai {
1512352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1513352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1514e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1515352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1516352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1517352f7f91STakashi Iwai 	int badness = 0;
15180e614dd0STakashi Iwai 	struct nid_path *path;
1519352f7f91STakashi Iwai 
1520352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1521352f7f91STakashi Iwai 	if (old_pins >= 2)
1522352f7f91STakashi Iwai 		goto end_fill;
1523352f7f91STakashi Iwai 
1524e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1525352f7f91STakashi Iwai 	if (num_pins < 2)
1526352f7f91STakashi Iwai 		goto end_fill;
1527352f7f91STakashi Iwai 
1528352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1529352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1530352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1531352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1532352f7f91STakashi Iwai 
1533352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1534352f7f91STakashi Iwai 				continue;
1535352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1536352f7f91STakashi Iwai 				continue;
1537352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1538352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1539352f7f91STakashi Iwai 					break;
1540352f7f91STakashi Iwai 			}
1541352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1542352f7f91STakashi Iwai 				continue;
1543352f7f91STakashi Iwai 
1544352f7f91STakashi Iwai 			if (hardwired)
1545352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1546352f7f91STakashi Iwai 			else if (!dac)
1547352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1548352f7f91STakashi Iwai 			if (!dac) {
1549352f7f91STakashi Iwai 				badness++;
1550352f7f91STakashi Iwai 				continue;
1551352f7f91STakashi Iwai 			}
15523ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
15533ca529d3STakashi Iwai 						    -spec->mixer_nid);
15540c8c0f56STakashi Iwai 			if (!path) {
1555352f7f91STakashi Iwai 				badness++;
1556352f7f91STakashi Iwai 				continue;
1557352f7f91STakashi Iwai 			}
15584e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1559352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1560352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1561196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1562196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1563352f7f91STakashi Iwai 			spec->multi_ios++;
1564352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1565352f7f91STakashi Iwai 				break;
1566352f7f91STakashi Iwai 		}
1567352f7f91STakashi Iwai 	}
1568352f7f91STakashi Iwai  end_fill:
1569352f7f91STakashi Iwai 	if (badness)
1570352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1571352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1572352f7f91STakashi Iwai 		if (hardwired)
1573352f7f91STakashi Iwai 			return 1; /* nothing found */
1574352f7f91STakashi Iwai 		else
1575352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1576352f7f91STakashi Iwai 	}
1577352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1578352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1579352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1580352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1581352f7f91STakashi Iwai 		return badness;
1582352f7f91STakashi Iwai 	}
1583352f7f91STakashi Iwai 
1584352f7f91STakashi Iwai 	/* assign volume and mute controls */
15850e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
15860e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
15870e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
15880e614dd0STakashi Iwai 	}
1589352f7f91STakashi Iwai 
1590352f7f91STakashi Iwai 	return badness;
1591352f7f91STakashi Iwai }
1592352f7f91STakashi Iwai 
1593352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1594352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1595196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1596352f7f91STakashi Iwai {
1597b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1598352f7f91STakashi Iwai 	int i;
1599352f7f91STakashi Iwai 	bool found = false;
1600352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
16010c8c0f56STakashi Iwai 		struct nid_path *path;
1602352f7f91STakashi Iwai 		hda_nid_t dac;
1603352f7f91STakashi Iwai 		if (dacs[i])
1604352f7f91STakashi Iwai 			continue;
1605352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1606352f7f91STakashi Iwai 		if (!dac)
1607352f7f91STakashi Iwai 			continue;
16083ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
16093ca529d3STakashi Iwai 					    -spec->mixer_nid);
1610117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
16113ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
16120c8c0f56STakashi Iwai 		if (path) {
1613352f7f91STakashi Iwai 			dacs[i] = dac;
1614352f7f91STakashi Iwai 			found = true;
16154e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1616e1284af7STakashi Iwai 			path->active = true;
1617196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1618352f7f91STakashi Iwai 		}
1619352f7f91STakashi Iwai 	}
1620352f7f91STakashi Iwai 	return found;
1621352f7f91STakashi Iwai }
1622352f7f91STakashi Iwai 
1623e7fdd527STakashi Iwai static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1624e7fdd527STakashi Iwai {
1625e7fdd527STakashi Iwai 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1626e7fdd527STakashi Iwai 		spec->aamix_out_paths[2];
1627e7fdd527STakashi Iwai }
1628e7fdd527STakashi Iwai 
1629c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1630c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1631c30aa7b2STakashi Iwai {
16323ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1633c30aa7b2STakashi Iwai 	struct nid_path *path;
16345ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1635c30aa7b2STakashi Iwai 
1636c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
16373ca529d3STakashi Iwai 	if (!path || !path->depth ||
16383ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1639c30aa7b2STakashi Iwai 		return 0;
16405ead56f2STakashi Iwai 	path_dac = path->path[0];
16415ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1642f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1643f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1644f87498b6STakashi Iwai 	if (!path) {
16455ead56f2STakashi Iwai 		if (dac != path_dac)
16465ead56f2STakashi Iwai 			dac = path_dac;
1647f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1648f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1649f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1650f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
16515ead56f2STakashi Iwai 		else
16525ead56f2STakashi Iwai 			dac = 0;
1653f87498b6STakashi Iwai 		if (dac)
1654f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
16553ca529d3STakashi Iwai 						    spec->mixer_nid);
1656f87498b6STakashi Iwai 	}
1657c30aa7b2STakashi Iwai 	if (!path)
1658c30aa7b2STakashi Iwai 		return 0;
16594e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1660c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
16616b275b14STakashi Iwai 	path->pin_fixed = true; /* static route */
1662c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1663c30aa7b2STakashi Iwai }
1664c30aa7b2STakashi Iwai 
166555a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
166655a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
166755a63d4dSTakashi Iwai {
166855a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
166955a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
167055a63d4dSTakashi Iwai 	struct nid_path *path;
167155a63d4dSTakashi Iwai 	int i, idx;
167255a63d4dSTakashi Iwai 
167355a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
167455a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
167555a63d4dSTakashi Iwai 	else
167655a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
167755a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
167855a63d4dSTakashi Iwai 	if (!path)
167955a63d4dSTakashi Iwai 		return false;
168055a63d4dSTakashi Iwai 
168155a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
168255a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
168355a63d4dSTakashi Iwai 		return true;
168455a63d4dSTakashi Iwai 
168555a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
168655a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
168755a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
168855a63d4dSTakashi Iwai 			break;
168955a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
169055a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
169155a63d4dSTakashi Iwai 			return false;
169255a63d4dSTakashi Iwai 	}
169355a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
169455a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
169555a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
169655a63d4dSTakashi Iwai 			return false;
169755a63d4dSTakashi Iwai 	}
169855a63d4dSTakashi Iwai 
169955a63d4dSTakashi Iwai 	return true;
170055a63d4dSTakashi Iwai }
170155a63d4dSTakashi Iwai 
1702a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1703a07a949bSTakashi Iwai  * shared dac pointed by the paths
1704a07a949bSTakashi Iwai  */
1705a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1706a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1707a07a949bSTakashi Iwai {
1708a07a949bSTakashi Iwai 	struct nid_path *path;
1709a07a949bSTakashi Iwai 	int i;
1710a07a949bSTakashi Iwai 
1711a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1712a07a949bSTakashi Iwai 		if (dacs[i])
1713a07a949bSTakashi Iwai 			continue;
1714a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1715a07a949bSTakashi Iwai 		if (!path)
1716a07a949bSTakashi Iwai 			continue;
1717a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1718a07a949bSTakashi Iwai 	}
1719a07a949bSTakashi Iwai }
1720a07a949bSTakashi Iwai 
1721352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1722352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1723352f7f91STakashi Iwai 			      bool fill_hardwired,
1724352f7f91STakashi Iwai 			      bool fill_mio_first)
1725352f7f91STakashi Iwai {
1726352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1727352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1728352f7f91STakashi Iwai 	int i, err, badness;
1729352f7f91STakashi Iwai 
1730352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1731352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1732352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1733352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1734352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1735352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1736352f7f91STakashi Iwai 	spec->multi_ios = 0;
1737352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1738cd5be3f9STakashi Iwai 
1739cd5be3f9STakashi Iwai 	/* clear path indices */
1740cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1741cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1742cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1743cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1744cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1745c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1746cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1747cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1748cd5be3f9STakashi Iwai 
1749352f7f91STakashi Iwai 	badness = 0;
1750352f7f91STakashi Iwai 
1751352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1752352f7f91STakashi Iwai 	if (fill_hardwired) {
1753352f7f91STakashi Iwai 		bool mapped;
1754352f7f91STakashi Iwai 		do {
1755352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1756352f7f91STakashi Iwai 					     cfg->line_out_pins,
1757196c1766STakashi Iwai 					     spec->private_dac_nids,
1758196c1766STakashi Iwai 					     spec->out_paths);
1759352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1760352f7f91STakashi Iwai 					      cfg->hp_pins,
1761196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1762196c1766STakashi Iwai 					      spec->hp_paths);
1763352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1764352f7f91STakashi Iwai 					      cfg->speaker_pins,
1765196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1766196c1766STakashi Iwai 					      spec->speaker_paths);
1767da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1768da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1769352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1770e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1771352f7f91STakashi Iwai 				if (!err)
1772352f7f91STakashi Iwai 					mapped = true;
1773352f7f91STakashi Iwai 			}
1774352f7f91STakashi Iwai 		} while (mapped);
1775352f7f91STakashi Iwai 	}
1776352f7f91STakashi Iwai 
1777352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1778196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
177998bd1115STakashi Iwai 				   spec->main_out_badness);
1780352f7f91STakashi Iwai 
1781da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1782352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1783352f7f91STakashi Iwai 		/* try to fill multi-io first */
1784e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1785352f7f91STakashi Iwai 		if (err < 0)
1786352f7f91STakashi Iwai 			return err;
1787352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1788352f7f91STakashi Iwai 	}
1789352f7f91STakashi Iwai 
1790352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1791352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1792352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1793196c1766STakashi Iwai 				      spec->hp_paths,
179498bd1115STakashi Iwai 				      spec->extra_out_badness);
1795352f7f91STakashi Iwai 		if (err < 0)
1796352f7f91STakashi Iwai 			return err;
1797352f7f91STakashi Iwai 		badness += err;
1798352f7f91STakashi Iwai 	}
1799352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1800352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1801352f7f91STakashi Iwai 				      cfg->speaker_pins,
1802352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1803196c1766STakashi Iwai 				      spec->speaker_paths,
180498bd1115STakashi Iwai 				      spec->extra_out_badness);
1805352f7f91STakashi Iwai 		if (err < 0)
1806352f7f91STakashi Iwai 			return err;
1807352f7f91STakashi Iwai 		badness += err;
1808352f7f91STakashi Iwai 	}
1809da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1810da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1811e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1812352f7f91STakashi Iwai 		if (err < 0)
1813352f7f91STakashi Iwai 			return err;
1814352f7f91STakashi Iwai 		badness += err;
1815352f7f91STakashi Iwai 	}
1816e22aab7dSTakashi Iwai 
1817c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1818c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1819c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1820c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1821c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1822c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1823c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1824c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1825c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1826c30aa7b2STakashi Iwai 	}
1827c30aa7b2STakashi Iwai 
1828da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1829da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1830e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1831e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1832352f7f91STakashi Iwai 
1833a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1834a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1835a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1836a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1837a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1838a07a949bSTakashi Iwai 		else {
1839a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1840a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1841a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1842a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1843a07a949bSTakashi Iwai 		}
1844a07a949bSTakashi Iwai 	}
1845a07a949bSTakashi Iwai 
1846a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1847c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1848a07a949bSTakashi Iwai 
1849352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1850352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1851352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1852352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1853352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1854352f7f91STakashi Iwai 		spec->multi_ios = 0;
1855352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1856352f7f91STakashi Iwai 	}
1857352f7f91STakashi Iwai 
185855a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
185955a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
186055a63d4dSTakashi Iwai 
1861a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1862a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1863a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1864a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1865a07a949bSTakashi Iwai 				   spec->hp_paths);
1866a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1867a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1868a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1869a07a949bSTakashi Iwai 				   spec->speaker_paths);
1870a07a949bSTakashi Iwai 
1871352f7f91STakashi Iwai 	return badness;
1872352f7f91STakashi Iwai }
1873352f7f91STakashi Iwai 
1874352f7f91STakashi Iwai #define DEBUG_BADNESS
1875352f7f91STakashi Iwai 
1876352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1877d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1878d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1879352f7f91STakashi Iwai #else
1880d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1881d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1882352f7f91STakashi Iwai #endif
1883352f7f91STakashi Iwai 
1884a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1885a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1886a769409cSTakashi Iwai 				      const char *pfx, int idx)
1887352f7f91STakashi Iwai {
1888a769409cSTakashi Iwai 	struct nid_path *path;
1889a769409cSTakashi Iwai 
1890a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1891a769409cSTakashi Iwai 	if (path)
18924e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1893a769409cSTakashi Iwai }
1894a769409cSTakashi Iwai 
1895a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1896a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1897a769409cSTakashi Iwai {
1898a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1899a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1900a769409cSTakashi Iwai 	int i;
1901a769409cSTakashi Iwai 
1902a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1903352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1904708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1905352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1906352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1907352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1908a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1909a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1910a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1911a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1912352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1913352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1914352f7f91STakashi Iwai 			      spec->multi_ios,
1915352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1916352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1917a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1918a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1919a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1920a769409cSTakashi Iwai 	if (cfg->hp_outs)
1921352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1922352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1923708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1924352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1925352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1926352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1927352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1928a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1929a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1930a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1931352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1932352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1933352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1934352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1935352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1936352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1937352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1938a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1939a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1940a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1941a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1942352f7f91STakashi Iwai }
1943a769409cSTakashi Iwai #else
1944a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1945a769409cSTakashi Iwai #endif
1946352f7f91STakashi Iwai 
1947352f7f91STakashi Iwai /* find all available DACs of the codec */
1948352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1949352f7f91STakashi Iwai {
1950352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
19517639a06cSTakashi Iwai 	hda_nid_t nid;
1952352f7f91STakashi Iwai 
1953352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1954352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
19557639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
1956352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1957352f7f91STakashi Iwai 			continue;
1958352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
19594e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1960352f7f91STakashi Iwai 			break;
1961352f7f91STakashi Iwai 		}
1962352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1963352f7f91STakashi Iwai 	}
1964352f7f91STakashi Iwai }
1965352f7f91STakashi Iwai 
1966352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1967352f7f91STakashi Iwai {
1968352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1969352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1970352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
19719314a581STakashi Iwai 	unsigned int val;
1972352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1973352f7f91STakashi Iwai 	int badness;
1974352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1975352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1976352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1977352f7f91STakashi Iwai 
1978352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1979352f7f91STakashi Iwai 	if (!best_cfg)
1980352f7f91STakashi Iwai 		return -ENOMEM;
1981352f7f91STakashi Iwai 	*best_cfg = *cfg;
1982352f7f91STakashi Iwai 
1983352f7f91STakashi Iwai 	for (;;) {
1984352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1985352f7f91STakashi Iwai 					     fill_mio_first);
1986352f7f91STakashi Iwai 		if (badness < 0) {
1987352f7f91STakashi Iwai 			kfree(best_cfg);
1988352f7f91STakashi Iwai 			return badness;
1989352f7f91STakashi Iwai 		}
1990352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
1991352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
1992352f7f91STakashi Iwai 			      badness);
1993a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
1994352f7f91STakashi Iwai 		if (badness < best_badness) {
1995352f7f91STakashi Iwai 			best_badness = badness;
1996352f7f91STakashi Iwai 			*best_cfg = *cfg;
1997352f7f91STakashi Iwai 			best_wired = fill_hardwired;
1998352f7f91STakashi Iwai 			best_mio = fill_mio_first;
1999352f7f91STakashi Iwai 		}
2000352f7f91STakashi Iwai 		if (!badness)
2001352f7f91STakashi Iwai 			break;
2002352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
2003352f7f91STakashi Iwai 		if (!fill_mio_first)
2004352f7f91STakashi Iwai 			continue;
2005352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
2006352f7f91STakashi Iwai 		if (!fill_hardwired)
2007352f7f91STakashi Iwai 			continue;
2008352f7f91STakashi Iwai 		if (hp_spk_swapped)
2009352f7f91STakashi Iwai 			break;
2010352f7f91STakashi Iwai 		hp_spk_swapped = true;
2011352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
2012352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2013352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
2014352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
2015352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2016352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
2017352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
2018352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2019352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
2020352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
2021352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
2022352f7f91STakashi Iwai 			fill_hardwired = true;
2023352f7f91STakashi Iwai 			continue;
2024352f7f91STakashi Iwai 		}
2025352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
2026352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2027352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
2028352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
2029352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2030352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
2031352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
2032352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2033352f7f91STakashi Iwai 			cfg->hp_outs = 0;
2034352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2035352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
2036352f7f91STakashi Iwai 			fill_hardwired = true;
2037352f7f91STakashi Iwai 			continue;
2038352f7f91STakashi Iwai 		}
2039352f7f91STakashi Iwai 		break;
2040352f7f91STakashi Iwai 	}
2041352f7f91STakashi Iwai 
2042352f7f91STakashi Iwai 	if (badness) {
20430c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
2044352f7f91STakashi Iwai 		*cfg = *best_cfg;
2045352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
2046352f7f91STakashi Iwai 	}
2047352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2048352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
2049a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
2050352f7f91STakashi Iwai 
2051352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
2052352f7f91STakashi Iwai 		struct nid_path *path;
2053196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2054352f7f91STakashi Iwai 		if (path)
2055352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2056d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
20577a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
20587a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
2059d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
206051cdc8b6STakashi Sakamoto 				spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
2061d89c6c0cSTakashi Iwai 		}
2062352f7f91STakashi Iwai 	}
2063352f7f91STakashi Iwai 
20649314a581STakashi Iwai 	/* set initial pinctl targets */
20659314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
20669314a581STakashi Iwai 		val = PIN_HP;
20679314a581STakashi Iwai 	else
20689314a581STakashi Iwai 		val = PIN_OUT;
20699314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
20709314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
20719314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
20729314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
20739314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
20749314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
20759314a581STakashi Iwai 				cfg->speaker_pins, val);
20769314a581STakashi Iwai 	}
20779314a581STakashi Iwai 
207855a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
207955a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
208055a63d4dSTakashi Iwai 		spec->indep_hp = 0;
208155a63d4dSTakashi Iwai 
2082352f7f91STakashi Iwai 	kfree(best_cfg);
2083352f7f91STakashi Iwai 	return 0;
2084352f7f91STakashi Iwai }
2085352f7f91STakashi Iwai 
2086352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
2087352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
2088352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
2089352f7f91STakashi Iwai {
2090352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2091352f7f91STakashi Iwai 	int i, err, noutputs;
2092352f7f91STakashi Iwai 
2093352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
2094352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2095352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
2096352f7f91STakashi Iwai 
2097352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
2098352f7f91STakashi Iwai 		const char *name;
2099352f7f91STakashi Iwai 		int index;
2100352f7f91STakashi Iwai 		struct nid_path *path;
2101352f7f91STakashi Iwai 
2102196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2103352f7f91STakashi Iwai 		if (!path)
2104352f7f91STakashi Iwai 			continue;
2105247d85eeSTakashi Iwai 
2106247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2107352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2108352f7f91STakashi Iwai 			/* Center/LFE */
2109352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2110352f7f91STakashi Iwai 			if (err < 0)
2111352f7f91STakashi Iwai 				return err;
2112352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2113352f7f91STakashi Iwai 			if (err < 0)
2114352f7f91STakashi Iwai 				return err;
2115247d85eeSTakashi Iwai 		} else {
2116247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2117247d85eeSTakashi Iwai 			if (err < 0)
2118247d85eeSTakashi Iwai 				return err;
2119247d85eeSTakashi Iwai 		}
2120247d85eeSTakashi Iwai 
2121247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2122247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2123352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2124352f7f91STakashi Iwai 			if (err < 0)
2125352f7f91STakashi Iwai 				return err;
2126352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2127352f7f91STakashi Iwai 			if (err < 0)
2128352f7f91STakashi Iwai 				return err;
2129352f7f91STakashi Iwai 		} else {
2130352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2131352f7f91STakashi Iwai 			if (err < 0)
2132352f7f91STakashi Iwai 				return err;
2133352f7f91STakashi Iwai 		}
2134352f7f91STakashi Iwai 	}
2135352f7f91STakashi Iwai 	return 0;
2136352f7f91STakashi Iwai }
2137352f7f91STakashi Iwai 
2138c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2139196c1766STakashi Iwai 			    const char *pfx, int cidx)
2140352f7f91STakashi Iwai {
2141352f7f91STakashi Iwai 	struct nid_path *path;
2142352f7f91STakashi Iwai 	int err;
2143352f7f91STakashi Iwai 
2144196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2145352f7f91STakashi Iwai 	if (!path)
2146352f7f91STakashi Iwai 		return 0;
2147352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2148352f7f91STakashi Iwai 	if (err < 0)
2149352f7f91STakashi Iwai 		return err;
2150352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2151352f7f91STakashi Iwai 	if (err < 0)
2152352f7f91STakashi Iwai 		return err;
2153352f7f91STakashi Iwai 	return 0;
2154352f7f91STakashi Iwai }
2155352f7f91STakashi Iwai 
2156352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2157352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2158196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2159352f7f91STakashi Iwai {
2160c2c80383STakashi Iwai 	int i;
2161352f7f91STakashi Iwai 
2162352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2163c2c80383STakashi Iwai 		const char *name;
2164975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2165c2c80383STakashi Iwai 		int err, idx = 0;
2166c2c80383STakashi Iwai 
2167c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2168c2c80383STakashi Iwai 			name = "Bass Speaker";
2169c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2170c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2171352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2172c2c80383STakashi Iwai 			name = tmp;
2173352f7f91STakashi Iwai 		} else {
2174c2c80383STakashi Iwai 			name = pfx;
2175c2c80383STakashi Iwai 			idx = i;
2176352f7f91STakashi Iwai 		}
2177c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2178352f7f91STakashi Iwai 		if (err < 0)
2179352f7f91STakashi Iwai 			return err;
2180352f7f91STakashi Iwai 	}
2181352f7f91STakashi Iwai 	return 0;
2182352f7f91STakashi Iwai }
2183352f7f91STakashi Iwai 
2184352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2185352f7f91STakashi Iwai {
2186352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2187352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2188196c1766STakashi Iwai 				 spec->hp_paths,
2189352f7f91STakashi Iwai 				 "Headphone");
2190352f7f91STakashi Iwai }
2191352f7f91STakashi Iwai 
2192352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2193352f7f91STakashi Iwai {
2194352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2195352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2196196c1766STakashi Iwai 				 spec->speaker_paths,
2197352f7f91STakashi Iwai 				 "Speaker");
2198352f7f91STakashi Iwai }
2199352f7f91STakashi Iwai 
2200352f7f91STakashi Iwai /*
220138cf6f1aSTakashi Iwai  * independent HP controls
220238cf6f1aSTakashi Iwai  */
220338cf6f1aSTakashi Iwai 
22041a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
22051a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
220638cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
220738cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
220838cf6f1aSTakashi Iwai {
220938cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
221038cf6f1aSTakashi Iwai }
221138cf6f1aSTakashi Iwai 
221238cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
221338cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
221438cf6f1aSTakashi Iwai {
221538cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
221638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
221738cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
221838cf6f1aSTakashi Iwai 	return 0;
221938cf6f1aSTakashi Iwai }
222038cf6f1aSTakashi Iwai 
2221a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2222a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2223a1e908edSTakashi Iwai 			       int out_type);
2224a1e908edSTakashi Iwai 
222538cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
222638cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
222738cf6f1aSTakashi Iwai {
222838cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
222938cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
223038cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
223138cf6f1aSTakashi Iwai 	int ret = 0;
223238cf6f1aSTakashi Iwai 
223338cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
223438cf6f1aSTakashi Iwai 	if (spec->active_streams) {
223538cf6f1aSTakashi Iwai 		ret = -EBUSY;
223638cf6f1aSTakashi Iwai 		goto unlock;
223738cf6f1aSTakashi Iwai 	}
223838cf6f1aSTakashi Iwai 
223938cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2240a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2241a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2242a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2243a1e908edSTakashi Iwai 		else
2244a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2245a1e908edSTakashi Iwai 
2246a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2247a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2248a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2249a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2250a1e908edSTakashi Iwai 						   spec->out_paths[0],
2251a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2252a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2253a1e908edSTakashi Iwai 			else
2254a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2255a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2256a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2257a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2258a1e908edSTakashi Iwai 		}
2259a1e908edSTakashi Iwai 
226038cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
226138cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2262a1e908edSTakashi Iwai 			*dacp = 0;
226338cf6f1aSTakashi Iwai 		else
2264a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
226592603c59STakashi Iwai 
2266963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
226738cf6f1aSTakashi Iwai 		ret = 1;
226838cf6f1aSTakashi Iwai 	}
226938cf6f1aSTakashi Iwai  unlock:
227038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
227138cf6f1aSTakashi Iwai 	return ret;
227238cf6f1aSTakashi Iwai }
227338cf6f1aSTakashi Iwai 
227438cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
227538cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
227638cf6f1aSTakashi Iwai 	.name = "Independent HP",
227738cf6f1aSTakashi Iwai 	.info = indep_hp_info,
227838cf6f1aSTakashi Iwai 	.get = indep_hp_get,
227938cf6f1aSTakashi Iwai 	.put = indep_hp_put,
228038cf6f1aSTakashi Iwai };
228138cf6f1aSTakashi Iwai 
228238cf6f1aSTakashi Iwai 
228338cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
228438cf6f1aSTakashi Iwai {
228538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2286a1e908edSTakashi Iwai 	hda_nid_t dac;
228738cf6f1aSTakashi Iwai 
228838cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
228938cf6f1aSTakashi Iwai 		return 0;
2290a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2291a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2292a1e908edSTakashi Iwai 	else
2293a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2294a1e908edSTakashi Iwai 	if (!dac) {
229538cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
229638cf6f1aSTakashi Iwai 		return 0;
229738cf6f1aSTakashi Iwai 	}
229838cf6f1aSTakashi Iwai 
229938cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2300a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
230138cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
230238cf6f1aSTakashi Iwai 		return -ENOMEM;
230338cf6f1aSTakashi Iwai 	return 0;
230438cf6f1aSTakashi Iwai }
230538cf6f1aSTakashi Iwai 
230638cf6f1aSTakashi Iwai /*
2307352f7f91STakashi Iwai  * channel mode enum control
2308352f7f91STakashi Iwai  */
2309352f7f91STakashi Iwai 
2310352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2311352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2312352f7f91STakashi Iwai {
2313352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2314352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2315a07a949bSTakashi Iwai 	int chs;
2316352f7f91STakashi Iwai 
2317352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2318352f7f91STakashi Iwai 	uinfo->count = 1;
2319352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2320352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2321352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2322a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2323a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2324352f7f91STakashi Iwai 	return 0;
2325352f7f91STakashi Iwai }
2326352f7f91STakashi Iwai 
2327352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2328352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2329352f7f91STakashi Iwai {
2330352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2331352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2332a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2333a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2334352f7f91STakashi Iwai 	return 0;
2335352f7f91STakashi Iwai }
2336352f7f91STakashi Iwai 
2337196c1766STakashi Iwai static inline struct nid_path *
2338196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2339196c1766STakashi Iwai {
2340196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2341196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2342196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2343196c1766STakashi Iwai }
2344196c1766STakashi Iwai 
2345a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2346a5cc2509STakashi Iwai 
234765033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
234865033cc8STakashi Iwai  * used for output paths
234965033cc8STakashi Iwai  */
235065033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
235165033cc8STakashi Iwai {
235265033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
235365033cc8STakashi Iwai }
235465033cc8STakashi Iwai 
2355352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2356352f7f91STakashi Iwai {
2357352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2358352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2359352f7f91STakashi Iwai 	struct nid_path *path;
2360352f7f91STakashi Iwai 
2361196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2362352f7f91STakashi Iwai 	if (!path)
2363352f7f91STakashi Iwai 		return -EINVAL;
2364352f7f91STakashi Iwai 
2365352f7f91STakashi Iwai 	if (path->active == output)
2366352f7f91STakashi Iwai 		return 0;
2367352f7f91STakashi Iwai 
2368352f7f91STakashi Iwai 	if (output) {
23692c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
237065033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2371d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2372352f7f91STakashi Iwai 	} else {
2373d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
237465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
23752c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
237655196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2377352f7f91STakashi Iwai 	}
2378a365fed9STakashi Iwai 
2379a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2380a5cc2509STakashi Iwai 	update_automute_all(codec);
2381a365fed9STakashi Iwai 
2382352f7f91STakashi Iwai 	return 0;
2383352f7f91STakashi Iwai }
2384352f7f91STakashi Iwai 
2385352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2386352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2387352f7f91STakashi Iwai {
2388352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2389352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2390352f7f91STakashi Iwai 	int i, ch;
2391352f7f91STakashi Iwai 
2392352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2393352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2394352f7f91STakashi Iwai 		return -EINVAL;
2395a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2396352f7f91STakashi Iwai 		return 0;
2397a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2398352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2399352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2400352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2401352f7f91STakashi Iwai 					  spec->const_channel_count);
2402352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2403352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2404352f7f91STakashi Iwai 	return 1;
2405352f7f91STakashi Iwai }
2406352f7f91STakashi Iwai 
2407352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2408352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2409352f7f91STakashi Iwai 	.name = "Channel Mode",
2410352f7f91STakashi Iwai 	.info = ch_mode_info,
2411352f7f91STakashi Iwai 	.get = ch_mode_get,
2412352f7f91STakashi Iwai 	.put = ch_mode_put,
2413352f7f91STakashi Iwai };
2414352f7f91STakashi Iwai 
2415352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2416352f7f91STakashi Iwai {
2417352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2418352f7f91STakashi Iwai 
2419352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
242012c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2421352f7f91STakashi Iwai 			return -ENOMEM;
2422352f7f91STakashi Iwai 	}
2423352f7f91STakashi Iwai 	return 0;
2424352f7f91STakashi Iwai }
2425352f7f91STakashi Iwai 
2426352f7f91STakashi Iwai /*
2427c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2428c30aa7b2STakashi Iwai  */
2429c30aa7b2STakashi Iwai 
2430c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2431c30aa7b2STakashi Iwai 
2432c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2433c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2434c30aa7b2STakashi Iwai {
2435c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2436c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2437c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2438c30aa7b2STakashi Iwai 	return 0;
2439c30aa7b2STakashi Iwai }
2440c30aa7b2STakashi Iwai 
2441c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2442a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2443a1e908edSTakashi Iwai 			       int out_type)
2444c30aa7b2STakashi Iwai {
2445a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2446c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2447c30aa7b2STakashi Iwai 
2448c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2449c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2450c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2451c30aa7b2STakashi Iwai 		return;
2452a1e908edSTakashi Iwai 
2453a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2454a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2455a1e908edSTakashi Iwai 	 */
2456a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2457a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2458a1e908edSTakashi Iwai 		do_mix = false;
2459a1e908edSTakashi Iwai 
2460c30aa7b2STakashi Iwai 	if (do_mix) {
2461c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2462c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
246355196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2464c30aa7b2STakashi Iwai 	} else {
246565033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
246665033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
246755196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2468c30aa7b2STakashi Iwai 	}
2469c30aa7b2STakashi Iwai }
2470c30aa7b2STakashi Iwai 
2471e7fdd527STakashi Iwai /* re-initialize the output paths; only called from loopback_mixing_put() */
2472e7fdd527STakashi Iwai static void update_output_paths(struct hda_codec *codec, int num_outs,
2473e7fdd527STakashi Iwai 				const int *paths)
2474e7fdd527STakashi Iwai {
2475e7fdd527STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2476e7fdd527STakashi Iwai 	struct nid_path *path;
2477e7fdd527STakashi Iwai 	int i;
2478e7fdd527STakashi Iwai 
2479e7fdd527STakashi Iwai 	for (i = 0; i < num_outs; i++) {
2480e7fdd527STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2481e7fdd527STakashi Iwai 		if (path)
2482e7fdd527STakashi Iwai 			snd_hda_activate_path(codec, path, path->active,
2483e7fdd527STakashi Iwai 					      spec->aamix_mode);
2484e7fdd527STakashi Iwai 	}
2485e7fdd527STakashi Iwai }
2486e7fdd527STakashi Iwai 
2487c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2488c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2489c30aa7b2STakashi Iwai {
2490c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2491c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2492e7fdd527STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2493c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2494c30aa7b2STakashi Iwai 
2495c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2496c30aa7b2STakashi Iwai 		return 0;
2497c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2498e7fdd527STakashi Iwai 	if (has_aamix_out_paths(spec)) {
2499c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->out_paths[0],
2500a1e908edSTakashi Iwai 				   spec->aamix_out_paths[0],
2501e7fdd527STakashi Iwai 				   cfg->line_out_type);
2502c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->hp_paths[0],
2503a1e908edSTakashi Iwai 				   spec->aamix_out_paths[1],
2504a1e908edSTakashi Iwai 				   AUTO_PIN_HP_OUT);
2505c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2506a1e908edSTakashi Iwai 				   spec->aamix_out_paths[2],
2507a1e908edSTakashi Iwai 				   AUTO_PIN_SPEAKER_OUT);
2508e7fdd527STakashi Iwai 	} else {
2509e7fdd527STakashi Iwai 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2510e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2511e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2512e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2513e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->speaker_outs,
2514e7fdd527STakashi Iwai 					    spec->speaker_paths);
2515e7fdd527STakashi Iwai 	}
2516c30aa7b2STakashi Iwai 	return 1;
2517c30aa7b2STakashi Iwai }
2518c30aa7b2STakashi Iwai 
2519c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2520c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2521c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2522c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2523c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2524c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2525c30aa7b2STakashi Iwai };
2526c30aa7b2STakashi Iwai 
2527c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2528c30aa7b2STakashi Iwai {
2529c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2530c30aa7b2STakashi Iwai 
2531c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2532c30aa7b2STakashi Iwai 		return 0;
2533c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2534c30aa7b2STakashi Iwai 		return -ENOMEM;
2535a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2536c30aa7b2STakashi Iwai 	return 0;
2537c30aa7b2STakashi Iwai }
2538c30aa7b2STakashi Iwai 
2539c30aa7b2STakashi Iwai /*
2540352f7f91STakashi Iwai  * shared headphone/mic handling
2541352f7f91STakashi Iwai  */
2542352f7f91STakashi Iwai 
2543352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2544352f7f91STakashi Iwai 
2545352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2546967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2547352f7f91STakashi Iwai {
2548352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2549967303daSTakashi Iwai 	bool as_mic;
2550352f7f91STakashi Iwai 	unsigned int val;
2551967303daSTakashi Iwai 	hda_nid_t pin;
2552967303daSTakashi Iwai 
2553967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2554967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2555967303daSTakashi Iwai 
2556967303daSTakashi Iwai 	if (!force) {
2557967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2558967303daSTakashi Iwai 		if (as_mic) {
2559967303daSTakashi Iwai 			if (val & PIN_IN)
2560967303daSTakashi Iwai 				return;
2561967303daSTakashi Iwai 		} else {
2562967303daSTakashi Iwai 			if (val & PIN_OUT)
2563967303daSTakashi Iwai 				return;
2564967303daSTakashi Iwai 		}
2565967303daSTakashi Iwai 	}
2566352f7f91STakashi Iwai 
2567352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2568967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2569967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2570967303daSTakashi Iwai 	 */
2571352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2572352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2573352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2574352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
25757594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2576967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2577352f7f91STakashi Iwai 	}
2578352f7f91STakashi Iwai 
25798ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2580967303daSTakashi Iwai 		if (as_mic)
2581967303daSTakashi Iwai 			val |= PIN_IN;
2582967303daSTakashi Iwai 		else
2583967303daSTakashi Iwai 			val = PIN_HP;
25842c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2585963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
25868ba955ceSTakashi Iwai 	}
2587352f7f91STakashi Iwai }
2588352f7f91STakashi Iwai 
2589352f7f91STakashi Iwai /* create a shared input with the headphone out */
2590967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2591352f7f91STakashi Iwai {
2592352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2593352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2594352f7f91STakashi Iwai 	unsigned int defcfg;
2595352f7f91STakashi Iwai 	hda_nid_t nid;
2596352f7f91STakashi Iwai 
2597967303daSTakashi Iwai 	if (!spec->hp_mic) {
2598967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2599352f7f91STakashi Iwai 			return 0;
2600967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2601967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2602967303daSTakashi Iwai 		 */
2603967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2604967303daSTakashi Iwai 			return 0;
2605967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2606352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2607352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2608352f7f91STakashi Iwai 				return 0;
2609967303daSTakashi Iwai 		}
2610967303daSTakashi Iwai 	}
2611352f7f91STakashi Iwai 
2612967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2613967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2614967303daSTakashi Iwai 		return 0;
2615967303daSTakashi Iwai 
2616967303daSTakashi Iwai 	nid = 0;
2617967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2618967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2619967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2620967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2621967303daSTakashi Iwai 	if (!nid)
2622967303daSTakashi Iwai 		return 0;
2623352f7f91STakashi Iwai 
2624352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2625352f7f91STakashi Iwai 		return 0; /* no input */
2626352f7f91STakashi Iwai 
2627967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2628967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2629cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2630967303daSTakashi Iwai 	cfg->num_inputs++;
2631967303daSTakashi Iwai 	spec->hp_mic = 1;
2632967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2633967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2634967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
26354e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2636352f7f91STakashi Iwai 	return 0;
2637352f7f91STakashi Iwai }
2638352f7f91STakashi Iwai 
2639978e77e7STakashi Iwai /*
2640978e77e7STakashi Iwai  * output jack mode
2641978e77e7STakashi Iwai  */
26425f171baaSTakashi Iwai 
26435f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
26445f171baaSTakashi Iwai 
26455f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
26465f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
26475f171baaSTakashi Iwai };
26485f171baaSTakashi Iwai 
2649978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2650978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2651978e77e7STakashi Iwai {
26525f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2653978e77e7STakashi Iwai }
2654978e77e7STakashi Iwai 
2655978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2656978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2657978e77e7STakashi Iwai {
2658978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2659978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2660978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2661978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2662978e77e7STakashi Iwai 	else
2663978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2664978e77e7STakashi Iwai 	return 0;
2665978e77e7STakashi Iwai }
2666978e77e7STakashi Iwai 
2667978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2668978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2669978e77e7STakashi Iwai {
2670978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2671978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2672978e77e7STakashi Iwai 	unsigned int val;
2673978e77e7STakashi Iwai 
2674978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2675978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2676978e77e7STakashi Iwai 		return 0;
2677978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2678978e77e7STakashi Iwai 	return 1;
2679978e77e7STakashi Iwai }
2680978e77e7STakashi Iwai 
2681978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2682978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2683978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2684978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2685978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2686978e77e7STakashi Iwai };
2687978e77e7STakashi Iwai 
2688978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2689978e77e7STakashi Iwai {
2690978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2691a9c2dfc8STakashi Iwai 	const struct snd_kcontrol_new *kctl;
2692978e77e7STakashi Iwai 	int i;
2693978e77e7STakashi Iwai 
2694a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->kctls, i, kctl) {
2695978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2696978e77e7STakashi Iwai 			return true;
2697978e77e7STakashi Iwai 	}
2698978e77e7STakashi Iwai 	return false;
2699978e77e7STakashi Iwai }
2700978e77e7STakashi Iwai 
2701978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2702978e77e7STakashi Iwai 			       char *name, size_t name_len)
2703978e77e7STakashi Iwai {
2704978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2705978e77e7STakashi Iwai 	int idx = 0;
2706978e77e7STakashi Iwai 
2707978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2708978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2709978e77e7STakashi Iwai 
2710978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2711978e77e7STakashi Iwai 		;
2712978e77e7STakashi Iwai }
2713978e77e7STakashi Iwai 
27145f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
27155f171baaSTakashi Iwai {
27165f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2717f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
27185f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
27195f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
27205f171baaSTakashi Iwai 			return 2;
27215f171baaSTakashi Iwai 	}
27225f171baaSTakashi Iwai 	return 1;
27235f171baaSTakashi Iwai }
27245f171baaSTakashi Iwai 
2725978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2726978e77e7STakashi Iwai 				 hda_nid_t *pins)
2727978e77e7STakashi Iwai {
2728978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2729978e77e7STakashi Iwai 	int i;
2730978e77e7STakashi Iwai 
2731978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2732978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2733ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
27345f171baaSTakashi Iwai 			continue;
27355f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2736978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2737975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2738978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2739978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2740978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2741978e77e7STakashi Iwai 			if (!knew)
2742978e77e7STakashi Iwai 				return -ENOMEM;
2743978e77e7STakashi Iwai 			knew->private_value = pin;
2744978e77e7STakashi Iwai 		}
2745978e77e7STakashi Iwai 	}
2746978e77e7STakashi Iwai 
2747978e77e7STakashi Iwai 	return 0;
2748978e77e7STakashi Iwai }
2749978e77e7STakashi Iwai 
275029476558STakashi Iwai /*
275129476558STakashi Iwai  * input jack mode
275229476558STakashi Iwai  */
275329476558STakashi Iwai 
275429476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
275529476558STakashi Iwai #define NUM_VREFS	6
275629476558STakashi Iwai 
275729476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
275829476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
275929476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
276029476558STakashi Iwai };
276129476558STakashi Iwai 
276229476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
276329476558STakashi Iwai {
276429476558STakashi Iwai 	unsigned int pincap;
276529476558STakashi Iwai 
276629476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
276729476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
276829476558STakashi Iwai 	/* filter out unusual vrefs */
276929476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
277029476558STakashi Iwai 	return pincap;
277129476558STakashi Iwai }
277229476558STakashi Iwai 
277329476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
277429476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
277529476558STakashi Iwai {
277629476558STakashi Iwai 	unsigned int i, n = 0;
277729476558STakashi Iwai 
277829476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
277929476558STakashi Iwai 		if (vref_caps & (1 << i)) {
278029476558STakashi Iwai 			if (n == item_idx)
278129476558STakashi Iwai 				return i;
278229476558STakashi Iwai 			n++;
278329476558STakashi Iwai 		}
278429476558STakashi Iwai 	}
278529476558STakashi Iwai 	return 0;
278629476558STakashi Iwai }
278729476558STakashi Iwai 
278829476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
278929476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
279029476558STakashi Iwai {
279129476558STakashi Iwai 	unsigned int i, n = 0;
279229476558STakashi Iwai 
279329476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
279429476558STakashi Iwai 		if (i == idx)
279529476558STakashi Iwai 			return n;
279629476558STakashi Iwai 		if (vref_caps & (1 << i))
279729476558STakashi Iwai 			n++;
279829476558STakashi Iwai 	}
279929476558STakashi Iwai 	return 0;
280029476558STakashi Iwai }
280129476558STakashi Iwai 
280229476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
280329476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
280429476558STakashi Iwai {
280529476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
280629476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
280729476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
280829476558STakashi Iwai 
280929476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
281029476558STakashi Iwai 				 vref_texts);
281129476558STakashi Iwai 	/* set the right text */
281229476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
281329476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
281429476558STakashi Iwai 	return 0;
281529476558STakashi Iwai }
281629476558STakashi Iwai 
281729476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
281829476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
281929476558STakashi Iwai {
282029476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
282129476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
282229476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
282329476558STakashi Iwai 	unsigned int idx;
282429476558STakashi Iwai 
282529476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
282629476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
282729476558STakashi Iwai 	return 0;
282829476558STakashi Iwai }
282929476558STakashi Iwai 
283029476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
283129476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
283229476558STakashi Iwai {
283329476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
283429476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
283529476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
283629476558STakashi Iwai 	unsigned int val, idx;
283729476558STakashi Iwai 
283829476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
283929476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
284029476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
284129476558STakashi Iwai 		return 0;
284229476558STakashi Iwai 
284329476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
284429476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
284529476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
284629476558STakashi Iwai 	return 1;
284729476558STakashi Iwai }
284829476558STakashi Iwai 
284929476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
285029476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
285129476558STakashi Iwai 	.info = in_jack_mode_info,
285229476558STakashi Iwai 	.get = in_jack_mode_get,
285329476558STakashi Iwai 	.put = in_jack_mode_put,
285429476558STakashi Iwai };
285529476558STakashi Iwai 
28565f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
28575f171baaSTakashi Iwai {
28585f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28595f171baaSTakashi Iwai 	int nitems = 0;
2860f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
28615f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
28625f171baaSTakashi Iwai 	return nitems ? nitems : 1;
28635f171baaSTakashi Iwai }
28645f171baaSTakashi Iwai 
286529476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
286629476558STakashi Iwai {
286729476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
286829476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2869975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
28705f171baaSTakashi Iwai 	unsigned int defcfg;
28715f171baaSTakashi Iwai 
2872f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2873f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
287429476558STakashi Iwai 
287529476558STakashi Iwai 	/* no jack mode for fixed pins */
287629476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
287729476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
287829476558STakashi Iwai 		return 0;
287929476558STakashi Iwai 
288029476558STakashi Iwai 	/* no multiple vref caps? */
28815f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
288229476558STakashi Iwai 		return 0;
288329476558STakashi Iwai 
288429476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
288529476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
288629476558STakashi Iwai 	if (!knew)
288729476558STakashi Iwai 		return -ENOMEM;
288829476558STakashi Iwai 	knew->private_value = pin;
288929476558STakashi Iwai 	return 0;
289029476558STakashi Iwai }
289129476558STakashi Iwai 
28925f171baaSTakashi Iwai /*
28935f171baaSTakashi Iwai  * HP/mic shared jack mode
28945f171baaSTakashi Iwai  */
28955f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
28965f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
28975f171baaSTakashi Iwai {
28985f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
28995f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29005f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29015f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29025f171baaSTakashi Iwai 	const char *text = NULL;
29035f171baaSTakashi Iwai 	int idx;
29045f171baaSTakashi Iwai 
29055f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
29065f171baaSTakashi Iwai 	uinfo->count = 1;
29075f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
29085f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
29095f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
29105f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
29115f171baaSTakashi Iwai 	if (idx < out_jacks) {
29125f171baaSTakashi Iwai 		if (out_jacks > 1)
29135f171baaSTakashi Iwai 			text = out_jack_texts[idx];
29145f171baaSTakashi Iwai 		else
29155f171baaSTakashi Iwai 			text = "Headphone Out";
29165f171baaSTakashi Iwai 	} else {
29175f171baaSTakashi Iwai 		idx -= out_jacks;
29185f171baaSTakashi Iwai 		if (in_jacks > 1) {
29195f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29205f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
29215f171baaSTakashi Iwai 		} else
29225f171baaSTakashi Iwai 			text = "Mic In";
29235f171baaSTakashi Iwai 	}
29245f171baaSTakashi Iwai 
29255f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
29265f171baaSTakashi Iwai 	return 0;
29275f171baaSTakashi Iwai }
29285f171baaSTakashi Iwai 
29295f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
29305f171baaSTakashi Iwai {
29315f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29325f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29335f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
29345f171baaSTakashi Iwai 	int idx = 0;
29355f171baaSTakashi Iwai 
29365f171baaSTakashi Iwai 	if (val & PIN_OUT) {
29375f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
29385f171baaSTakashi Iwai 			idx = 1;
29395f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
29405f171baaSTakashi Iwai 		idx = out_jacks;
29415f171baaSTakashi Iwai 		if (in_jacks > 1) {
29425f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29435f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
29445f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
29455f171baaSTakashi Iwai 		}
29465f171baaSTakashi Iwai 	}
29475f171baaSTakashi Iwai 	return idx;
29485f171baaSTakashi Iwai }
29495f171baaSTakashi Iwai 
29505f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
29515f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29525f171baaSTakashi Iwai {
29535f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29545f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29555f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
29565f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
29575f171baaSTakashi Iwai 	return 0;
29585f171baaSTakashi Iwai }
29595f171baaSTakashi Iwai 
29605f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
29615f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29625f171baaSTakashi Iwai {
29635f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29645f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29655f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29665f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29675f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
29685f171baaSTakashi Iwai 
29695f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
29705f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
29715f171baaSTakashi Iwai 	if (oldval == idx)
29725f171baaSTakashi Iwai 		return 0;
29735f171baaSTakashi Iwai 
29745f171baaSTakashi Iwai 	if (idx < out_jacks) {
29755f171baaSTakashi Iwai 		if (out_jacks > 1)
29765f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
29775f171baaSTakashi Iwai 		else
29785f171baaSTakashi Iwai 			val = PIN_HP;
29795f171baaSTakashi Iwai 	} else {
29805f171baaSTakashi Iwai 		idx -= out_jacks;
29815f171baaSTakashi Iwai 		if (in_jacks > 1) {
29825f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29835f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
29843f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
29853f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
29865f171baaSTakashi Iwai 		} else
298716c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
29885f171baaSTakashi Iwai 	}
29895f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2990963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
29918ba955ceSTakashi Iwai 
29925f171baaSTakashi Iwai 	return 1;
29935f171baaSTakashi Iwai }
29945f171baaSTakashi Iwai 
29955f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
29965f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
29975f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
29985f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
29995f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
30005f171baaSTakashi Iwai };
30015f171baaSTakashi Iwai 
30025f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
30035f171baaSTakashi Iwai {
30045f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
30055f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
30065f171baaSTakashi Iwai 
30075f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
30085f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
30095f171baaSTakashi Iwai 	if (!knew)
30105f171baaSTakashi Iwai 		return -ENOMEM;
30115f171baaSTakashi Iwai 	knew->private_value = pin;
30128ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
30135f171baaSTakashi Iwai 	return 0;
30145f171baaSTakashi Iwai }
3015352f7f91STakashi Iwai 
3016352f7f91STakashi Iwai /*
3017352f7f91STakashi Iwai  * Parse input paths
3018352f7f91STakashi Iwai  */
3019352f7f91STakashi Iwai 
3020352f7f91STakashi Iwai /* add the powersave loopback-list entry */
30210186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
3022352f7f91STakashi Iwai {
3023352f7f91STakashi Iwai 	struct hda_amp_list *list;
3024352f7f91STakashi Iwai 
30250186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
30260186f4f4STakashi Iwai 	if (!list)
30270186f4f4STakashi Iwai 		return -ENOMEM;
3028352f7f91STakashi Iwai 	list->nid = mix;
3029352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
3030352f7f91STakashi Iwai 	list->idx = idx;
30310186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
30320186f4f4STakashi Iwai 	return 0;
3033cb53c626STakashi Iwai }
3034cb53c626STakashi Iwai 
30352ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
30362ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
30372ded3e5bSTakashi Iwai  */
30382ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
30392ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
30402ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
30412ded3e5bSTakashi Iwai {
30422ded3e5bSTakashi Iwai 	int idx, num_conns;
30432ded3e5bSTakashi Iwai 	const hda_nid_t *list;
30442ded3e5bSTakashi Iwai 	hda_nid_t nid;
30452ded3e5bSTakashi Iwai 
30462ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
30472ded3e5bSTakashi Iwai 	if (idx < 0)
30482ded3e5bSTakashi Iwai 		return false;
30492ded3e5bSTakashi Iwai 
30502ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
30512ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
30522ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30532ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
30542ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30552ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
30562ded3e5bSTakashi Iwai 		return true;
30572ded3e5bSTakashi Iwai 
30582ded3e5bSTakashi Iwai 	/* check leaf node */
30592ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
30602ded3e5bSTakashi Iwai 	if (num_conns < idx)
30612ded3e5bSTakashi Iwai 		return false;
30622ded3e5bSTakashi Iwai 	nid = list[idx];
306343a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
306443a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
30652ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
306643a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
306743a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
30682ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
30692ded3e5bSTakashi Iwai 
30702ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
30712ded3e5bSTakashi Iwai }
30722ded3e5bSTakashi Iwai 
3073352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
3074196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
3075196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3076352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
30771da177e4SLinus Torvalds {
3078352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3079352f7f91STakashi Iwai 	struct nid_path *path;
30802ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
3081352f7f91STakashi Iwai 	int err, idx;
30821da177e4SLinus Torvalds 
30832ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
30842ded3e5bSTakashi Iwai 		return 0;
3085352f7f91STakashi Iwai 
30863ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3087352f7f91STakashi Iwai 	if (!path)
3088352f7f91STakashi Iwai 		return -EINVAL;
30894e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
3090196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3091352f7f91STakashi Iwai 
3092352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
30932ded3e5bSTakashi Iwai 	if (mix_val) {
30942ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3095d13bd412STakashi Iwai 		if (err < 0)
30961da177e4SLinus Torvalds 			return err;
30972ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
30981da177e4SLinus Torvalds 	}
30991da177e4SLinus Torvalds 
31002ded3e5bSTakashi Iwai 	if (mute_val) {
31012ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3102d13bd412STakashi Iwai 		if (err < 0)
31031da177e4SLinus Torvalds 			return err;
31042ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
31051da177e4SLinus Torvalds 	}
31061da177e4SLinus Torvalds 
3107352f7f91STakashi Iwai 	path->active = true;
3108e6feb5d0STakashi Iwai 	path->stream_enabled = true; /* no DAC/ADC involved */
31090186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
31100186f4f4STakashi Iwai 	if (err < 0)
31110186f4f4STakashi Iwai 		return err;
3112e4a395e7STakashi Iwai 
3113e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3114e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
3115e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3116e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
3117e4a395e7STakashi Iwai 		if (path) {
31184e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
3119e4a395e7STakashi Iwai 			path->active = true;
31206b275b14STakashi Iwai 			path->pin_fixed = true; /* static route */
3121e6feb5d0STakashi Iwai 			path->stream_enabled = true; /* no DAC/ADC involved */
3122e4a395e7STakashi Iwai 			spec->loopback_merge_path =
3123e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
3124e4a395e7STakashi Iwai 		}
3125e4a395e7STakashi Iwai 	}
3126e4a395e7STakashi Iwai 
3127352f7f91STakashi Iwai 	return 0;
31281da177e4SLinus Torvalds }
31291da177e4SLinus Torvalds 
3130352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
31311da177e4SLinus Torvalds {
3132352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3133352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
3134352f7f91STakashi Iwai }
3135352f7f91STakashi Iwai 
3136352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
3137352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
3138352f7f91STakashi Iwai {
3139352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3140352f7f91STakashi Iwai 	hda_nid_t nid;
3141352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
3142352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
31437639a06cSTakashi Iwai 	int nums = 0;
3144352f7f91STakashi Iwai 
31457639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
3146352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3147352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3148352f7f91STakashi Iwai 
3149352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3150352f7f91STakashi Iwai 			continue;
3151352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3152352f7f91STakashi Iwai 		if (++nums >= max_nums)
3153352f7f91STakashi Iwai 			break;
3154352f7f91STakashi Iwai 	}
3155352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
31560ffd534eSTakashi Iwai 
31570ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
31580ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
31590ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
31600ffd534eSTakashi Iwai 
3161352f7f91STakashi Iwai 	return nums;
3162352f7f91STakashi Iwai }
3163352f7f91STakashi Iwai 
3164352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3165352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3166352f7f91STakashi Iwai  */
3167352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3168352f7f91STakashi Iwai {
3169352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3170352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
31713a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3172352f7f91STakashi Iwai 	int i, n, nums;
3173352f7f91STakashi Iwai 
3174352f7f91STakashi Iwai 	nums = 0;
31753a65bcdcSTakashi Iwai 	ok_bits = 0;
3176352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3177352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
31783a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3179352f7f91STakashi Iwai 				break;
3180352f7f91STakashi Iwai 		}
31813a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
31823a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
31833a65bcdcSTakashi Iwai 			nums++;
31843a65bcdcSTakashi Iwai 		}
3185352f7f91STakashi Iwai 	}
3186352f7f91STakashi Iwai 
31873a65bcdcSTakashi Iwai 	if (!ok_bits) {
3188352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3189352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3190352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
31913a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3192352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3193352f7f91STakashi Iwai 					break;
3194352f7f91STakashi Iwai 				}
3195352f7f91STakashi Iwai 			}
3196352f7f91STakashi Iwai 		}
3197352f7f91STakashi Iwai 
31984e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3199352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3200352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
32013a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
32023a65bcdcSTakashi Iwai 		nums = 0;
32033a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
32043a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
32053a65bcdcSTakashi Iwai 				continue;
32063a65bcdcSTakashi Iwai 			if (n != nums) {
32073a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3208980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3209980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3210980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
32113a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
32123a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
3213a8f20fd2SHui Wang 					spec->input_paths[i][n] = 0;
32143a65bcdcSTakashi Iwai 				}
3215980428ceSTakashi Iwai 			}
32163a65bcdcSTakashi Iwai 			nums++;
32173a65bcdcSTakashi Iwai 		}
3218352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3219352f7f91STakashi Iwai 	}
3220352f7f91STakashi Iwai 
3221967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3222967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
32234e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3224352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3225352f7f91STakashi Iwai 	}
3226352f7f91STakashi Iwai 
3227352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3228352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3229352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3230352f7f91STakashi Iwai 
32311da177e4SLinus Torvalds 	return 0;
32321da177e4SLinus Torvalds }
32331da177e4SLinus Torvalds 
3234f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3235f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
32369dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
32379dba205bSTakashi Iwai 				const char *label, int anchor)
3238f3fc0b0bSTakashi Iwai {
3239f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3240f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3241f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3242f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3243f3fc0b0bSTakashi Iwai 	int c;
3244f3fc0b0bSTakashi Iwai 
3245f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3246f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3247f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3248f3fc0b0bSTakashi Iwai 
3249f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3250f3fc0b0bSTakashi Iwai 			continue;
3251f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3252f3fc0b0bSTakashi Iwai 		if (!path)
3253f3fc0b0bSTakashi Iwai 			continue;
32544e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3255f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3256f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3257f3fc0b0bSTakashi Iwai 
3258f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3259967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3260967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3261f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
32626194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3263f3fc0b0bSTakashi Iwai 			imux_added = true;
3264f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3265f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3266f3fc0b0bSTakashi Iwai 		}
3267f3fc0b0bSTakashi Iwai 	}
3268f3fc0b0bSTakashi Iwai 
3269f3fc0b0bSTakashi Iwai 	return 0;
3270f3fc0b0bSTakashi Iwai }
3271f3fc0b0bSTakashi Iwai 
32721da177e4SLinus Torvalds /*
3273352f7f91STakashi Iwai  * create playback/capture controls for input pins
32741da177e4SLinus Torvalds  */
32759dba205bSTakashi Iwai 
3276c970042cSTakashi Iwai /* fill the label for each input at first */
3277c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3278c970042cSTakashi Iwai {
3279c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3280c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3281c970042cSTakashi Iwai 	int i;
3282c970042cSTakashi Iwai 
3283c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3284c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3285c970042cSTakashi Iwai 		const char *label;
3286c970042cSTakashi Iwai 		int j, idx;
3287c970042cSTakashi Iwai 
3288c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3289c970042cSTakashi Iwai 			continue;
3290c970042cSTakashi Iwai 
3291c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3292c970042cSTakashi Iwai 		idx = 0;
32938e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3294c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3295c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3296c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3297c970042cSTakashi Iwai 				break;
3298c970042cSTakashi Iwai 			}
3299c970042cSTakashi Iwai 		}
3300c970042cSTakashi Iwai 
3301c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3302c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3303c970042cSTakashi Iwai 	}
3304c970042cSTakashi Iwai 
3305c970042cSTakashi Iwai 	return 0;
3306c970042cSTakashi Iwai }
3307c970042cSTakashi Iwai 
33089dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
33099dba205bSTakashi Iwai 
3310352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3311a7da6ce5STakashi Iwai {
3312352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3313352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3314352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3315352f7f91STakashi Iwai 	int num_adcs;
3316c970042cSTakashi Iwai 	int i, err;
33172c12c30dSTakashi Iwai 	unsigned int val;
3318a7da6ce5STakashi Iwai 
3319352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3320352f7f91STakashi Iwai 	if (num_adcs < 0)
3321352f7f91STakashi Iwai 		return 0;
3322352f7f91STakashi Iwai 
3323c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3324c970042cSTakashi Iwai 	if (err < 0)
3325c970042cSTakashi Iwai 		return err;
3326c970042cSTakashi Iwai 
3327352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3328352f7f91STakashi Iwai 		hda_nid_t pin;
3329352f7f91STakashi Iwai 
3330352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3331352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3332352f7f91STakashi Iwai 			continue;
3333352f7f91STakashi Iwai 
33342c12c30dSTakashi Iwai 		val = PIN_IN;
33352c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
33362c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
33373e1b0c4aSTakashi Iwai 		if (pin != spec->hp_mic_pin &&
33383e1b0c4aSTakashi Iwai 		    !snd_hda_codec_get_pin_target(codec, pin))
33392c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
33402c12c30dSTakashi Iwai 
3341352f7f91STakashi Iwai 		if (mixer) {
3342352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3343196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3344c970042cSTakashi Iwai 						       spec->input_labels[i],
3345c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3346c970042cSTakashi Iwai 						       mixer);
3347a7da6ce5STakashi Iwai 				if (err < 0)
3348a7da6ce5STakashi Iwai 					return err;
3349a7da6ce5STakashi Iwai 			}
3350352f7f91STakashi Iwai 		}
3351352f7f91STakashi Iwai 
3352c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3353c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3354f3fc0b0bSTakashi Iwai 		if (err < 0)
3355f3fc0b0bSTakashi Iwai 			return err;
335629476558STakashi Iwai 
3357f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
335829476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
335929476558STakashi Iwai 			if (err < 0)
336029476558STakashi Iwai 				return err;
336129476558STakashi Iwai 		}
3362352f7f91STakashi Iwai 	}
3363f3fc0b0bSTakashi Iwai 
3364f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
336574f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
33669dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3367f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3368f3fc0b0bSTakashi Iwai 		if (err < 0)
3369f3fc0b0bSTakashi Iwai 			return err;
337082d04e10STakashi Iwai 		else
337182d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3372352f7f91STakashi Iwai 	}
3373352f7f91STakashi Iwai 
3374a7da6ce5STakashi Iwai 	return 0;
3375a7da6ce5STakashi Iwai }
3376a7da6ce5STakashi Iwai 
33771da177e4SLinus Torvalds 
3378352f7f91STakashi Iwai /*
3379352f7f91STakashi Iwai  * input source mux
3380352f7f91STakashi Iwai  */
3381352f7f91STakashi Iwai 
3382c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3383c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3384352f7f91STakashi Iwai {
3385352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3386b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3387b56fa1edSDavid Henningsson 		snd_BUG();
3388b56fa1edSDavid Henningsson 		return NULL;
3389b56fa1edSDavid Henningsson 	}
3390352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3391352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3392d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3393b56fa1edSDavid Henningsson 		snd_BUG();
3394b56fa1edSDavid Henningsson 		return NULL;
3395b56fa1edSDavid Henningsson 	}
3396c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
339797ec558aSTakashi Iwai }
3398352f7f91STakashi Iwai 
3399352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3400352f7f91STakashi Iwai 		      unsigned int idx);
3401352f7f91STakashi Iwai 
3402352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3403352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3404352f7f91STakashi Iwai {
3405352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3406352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3407352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3408352f7f91STakashi Iwai }
3409352f7f91STakashi Iwai 
3410352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3411352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3412352f7f91STakashi Iwai {
3413352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3414352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
34152a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
34162a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3417352f7f91STakashi Iwai 
3418352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
34191da177e4SLinus Torvalds 	return 0;
34201da177e4SLinus Torvalds }
34211da177e4SLinus Torvalds 
3422352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3423352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
34241da177e4SLinus Torvalds {
3425352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34262a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3427352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3428352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3429352f7f91STakashi Iwai }
3430352f7f91STakashi Iwai 
3431352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
34321da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3433352f7f91STakashi Iwai 	.name = "Input Source",
3434352f7f91STakashi Iwai 	.info = mux_enum_info,
3435352f7f91STakashi Iwai 	.get = mux_enum_get,
3436352f7f91STakashi Iwai 	.put = mux_enum_put,
34371da177e4SLinus Torvalds };
3438071c73adSTakashi Iwai 
343947d46abbSTakashi Iwai /*
344047d46abbSTakashi Iwai  * capture volume and capture switch ctls
344147d46abbSTakashi Iwai  */
344247d46abbSTakashi Iwai 
3443352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3444352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3445071c73adSTakashi Iwai 
344647d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3447352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3448352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3449352f7f91STakashi Iwai 			  put_call_t func, int type)
3450352f7f91STakashi Iwai {
3451352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3452352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3453352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3454352f7f91STakashi Iwai 	struct nid_path *path;
3455352f7f91STakashi Iwai 	int i, adc_idx, err = 0;
3456071c73adSTakashi Iwai 
3457352f7f91STakashi Iwai 	imux = &spec->input_mux;
3458a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3459352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
3460352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3461c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3462c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3463352f7f91STakashi Iwai 			continue;
3464352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3465352f7f91STakashi Iwai 		err = func(kcontrol, ucontrol);
3466352f7f91STakashi Iwai 		if (err < 0)
3467a551d914STakashi Iwai 			break;
3468352f7f91STakashi Iwai 	}
3469352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3470352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
34717fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3472352f7f91STakashi Iwai 	return err;
3473352f7f91STakashi Iwai }
3474352f7f91STakashi Iwai 
3475352f7f91STakashi Iwai /* capture volume ctl callbacks */
3476352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3477352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3478352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3479352f7f91STakashi Iwai 
3480352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3481352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3482352f7f91STakashi Iwai {
3483352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3484352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3485352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3486352f7f91STakashi Iwai }
3487352f7f91STakashi Iwai 
3488352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3489352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3490352f7f91STakashi Iwai 	.name = "Capture Volume",
3491352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3492352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3493352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3494352f7f91STakashi Iwai 	.info = cap_vol_info,
3495352f7f91STakashi Iwai 	.get = cap_vol_get,
3496352f7f91STakashi Iwai 	.put = cap_vol_put,
3497352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3498352f7f91STakashi Iwai };
3499352f7f91STakashi Iwai 
3500352f7f91STakashi Iwai /* capture switch ctl callbacks */
3501352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3502352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3503352f7f91STakashi Iwai 
3504352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3505352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3506352f7f91STakashi Iwai {
3507a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3508352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3509352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3510352f7f91STakashi Iwai }
3511352f7f91STakashi Iwai 
3512352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3513352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3514352f7f91STakashi Iwai 	.name = "Capture Switch",
3515352f7f91STakashi Iwai 	.info = cap_sw_info,
3516352f7f91STakashi Iwai 	.get = cap_sw_get,
3517352f7f91STakashi Iwai 	.put = cap_sw_put,
3518352f7f91STakashi Iwai };
3519352f7f91STakashi Iwai 
3520352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3521352f7f91STakashi Iwai {
3522352f7f91STakashi Iwai 	hda_nid_t nid;
3523352f7f91STakashi Iwai 	int i, depth;
3524352f7f91STakashi Iwai 
3525352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3526352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3527352f7f91STakashi Iwai 		if (depth >= path->depth)
3528352f7f91STakashi Iwai 			return -EINVAL;
3529352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3530352f7f91STakashi Iwai 		nid = path->path[i];
3531352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3532352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3533352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3534352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3535352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3536352f7f91STakashi Iwai 				int idx = path->idx[i];
3537352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3538352f7f91STakashi Iwai 					idx = 0;
3539352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3540352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3541352f7f91STakashi Iwai 			}
3542352f7f91STakashi Iwai 		}
3543352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3544352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3545352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3546352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3547352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3548352f7f91STakashi Iwai 				int idx = path->idx[i];
3549352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3550352f7f91STakashi Iwai 					idx = 0;
3551352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3552352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3553352f7f91STakashi Iwai 			}
3554352f7f91STakashi Iwai 		}
3555352f7f91STakashi Iwai 	}
3556352f7f91STakashi Iwai 	return 0;
3557352f7f91STakashi Iwai }
3558352f7f91STakashi Iwai 
3559352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3560352f7f91STakashi Iwai {
3561352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3562352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3563352f7f91STakashi Iwai 	unsigned int val;
3564352f7f91STakashi Iwai 	int i;
3565352f7f91STakashi Iwai 
3566352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3567352f7f91STakashi Iwai 		return false;
3568352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3569352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3570352f7f91STakashi Iwai 			continue;
3571352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3572352f7f91STakashi Iwai 			return false;
3573352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3574352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3575352f7f91STakashi Iwai 	}
3576352f7f91STakashi Iwai 	return false;
3577352f7f91STakashi Iwai }
3578352f7f91STakashi Iwai 
3579a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3580a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3581a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3582a35bd1e3STakashi Iwai {
3583a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3584a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3585a35bd1e3STakashi Iwai 	int ret;
3586a35bd1e3STakashi Iwai 
3587a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3588a35bd1e3STakashi Iwai 	if (ret < 0)
3589a35bd1e3STakashi Iwai 		return ret;
3590a35bd1e3STakashi Iwai 
3591a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
35927fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3593a35bd1e3STakashi Iwai 
3594a35bd1e3STakashi Iwai 	return ret;
3595a35bd1e3STakashi Iwai }
3596a35bd1e3STakashi Iwai 
3597352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3598352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3599352f7f91STakashi Iwai 			      bool inv_dmic)
3600352f7f91STakashi Iwai {
3601352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3602975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3603352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3604352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3605352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3606a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3607352f7f91STakashi Iwai 
3608352f7f91STakashi Iwai 	if (!ctl)
3609352f7f91STakashi Iwai 		return 0;
3610352f7f91STakashi Iwai 
3611352f7f91STakashi Iwai 	if (label)
3612352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3613352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3614352f7f91STakashi Iwai 	else
3615352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3616352f7f91STakashi Iwai 			 "Capture %s", sfx);
3617a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3618352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3619a35bd1e3STakashi Iwai 	if (!knew)
3620a35bd1e3STakashi Iwai 		return -ENOMEM;
3621a90229e0STakashi Iwai 	if (is_switch)
3622a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3623a35bd1e3STakashi Iwai 	if (!inv_dmic)
3624a35bd1e3STakashi Iwai 		return 0;
3625352f7f91STakashi Iwai 
3626352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3627352f7f91STakashi Iwai 	if (label)
3628352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3629352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3630352f7f91STakashi Iwai 	else
3631352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3632352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3633a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3634352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3635a35bd1e3STakashi Iwai 	if (!knew)
3636a35bd1e3STakashi Iwai 		return -ENOMEM;
3637a90229e0STakashi Iwai 	if (is_switch)
3638a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3639a35bd1e3STakashi Iwai 	return 0;
3640352f7f91STakashi Iwai }
3641352f7f91STakashi Iwai 
3642352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3643352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3644352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3645352f7f91STakashi Iwai 				     bool inv_dmic)
3646352f7f91STakashi Iwai {
3647352f7f91STakashi Iwai 	int err;
3648352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3649352f7f91STakashi Iwai 	if (err < 0)
3650352f7f91STakashi Iwai 		return err;
3651352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3652071c73adSTakashi Iwai 	if (err < 0)
3653071c73adSTakashi Iwai 		return err;
3654071c73adSTakashi Iwai 	return 0;
36551da177e4SLinus Torvalds }
3656071c73adSTakashi Iwai 
3657352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3658352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3659352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3660352f7f91STakashi Iwai {
3661352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3662352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3663352f7f91STakashi Iwai 
3664352f7f91STakashi Iwai 	if (vol_ctl) {
366512c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3666352f7f91STakashi Iwai 		if (!knew)
3667352f7f91STakashi Iwai 			return -ENOMEM;
3668352f7f91STakashi Iwai 		knew->index = idx;
3669352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3670352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3671352f7f91STakashi Iwai 	}
3672352f7f91STakashi Iwai 	if (sw_ctl) {
367312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3674352f7f91STakashi Iwai 		if (!knew)
3675352f7f91STakashi Iwai 			return -ENOMEM;
3676352f7f91STakashi Iwai 		knew->index = idx;
3677352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3678352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3679352f7f91STakashi Iwai 	}
3680352f7f91STakashi Iwai 	return 0;
3681352f7f91STakashi Iwai }
3682352f7f91STakashi Iwai 
3683352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3684352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3685352f7f91STakashi Iwai {
3686352f7f91STakashi Iwai 	struct nid_path *path;
3687352f7f91STakashi Iwai 	unsigned int ctl;
3688352f7f91STakashi Iwai 	int i;
3689352f7f91STakashi Iwai 
3690c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3691352f7f91STakashi Iwai 	if (!path)
3692352f7f91STakashi Iwai 		return 0;
3693352f7f91STakashi Iwai 	ctl = path->ctls[type];
3694352f7f91STakashi Iwai 	if (!ctl)
3695352f7f91STakashi Iwai 		return 0;
3696352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3697c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3698352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3699352f7f91STakashi Iwai 			return 0;
3700352f7f91STakashi Iwai 	}
3701352f7f91STakashi Iwai 	return ctl;
3702352f7f91STakashi Iwai }
3703352f7f91STakashi Iwai 
3704352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3705352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3706352f7f91STakashi Iwai {
3707352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3708352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3709c970042cSTakashi Iwai 	int i, err, type;
3710352f7f91STakashi Iwai 
3711352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3712352f7f91STakashi Iwai 		bool inv_dmic;
3713c970042cSTakashi Iwai 		int idx;
37149dba205bSTakashi Iwai 
3715c970042cSTakashi Iwai 		idx = imux->items[i].index;
3716c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
37179dba205bSTakashi Iwai 			continue;
3718352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3719352f7f91STakashi Iwai 
3720352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3721c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3722c970042cSTakashi Iwai 						 spec->input_labels[idx],
3723c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3724c970042cSTakashi Iwai 						 type,
3725352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3726352f7f91STakashi Iwai 						 inv_dmic);
3727d13bd412STakashi Iwai 			if (err < 0)
3728071c73adSTakashi Iwai 				return err;
3729352f7f91STakashi Iwai 		}
3730352f7f91STakashi Iwai 	}
3731071c73adSTakashi Iwai 	return 0;
3732352f7f91STakashi Iwai }
3733071c73adSTakashi Iwai 
3734352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3735352f7f91STakashi Iwai {
3736352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3737352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3738352f7f91STakashi Iwai 	int i, n, nums, err;
3739352f7f91STakashi Iwai 
3740352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3741352f7f91STakashi Iwai 		nums = 1;
3742352f7f91STakashi Iwai 	else
3743352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3744352f7f91STakashi Iwai 
3745352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3746352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3747624d914dSTakashi Iwai 		const char *name;
3748624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3749624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3750352f7f91STakashi Iwai 		if (!knew)
3751352f7f91STakashi Iwai 			return -ENOMEM;
3752352f7f91STakashi Iwai 		knew->count = nums;
3753352f7f91STakashi Iwai 	}
3754352f7f91STakashi Iwai 
3755352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3756352f7f91STakashi Iwai 		bool multi = false;
375799a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3758352f7f91STakashi Iwai 		bool inv_dmic = false;
3759352f7f91STakashi Iwai 		int vol, sw;
3760352f7f91STakashi Iwai 
3761352f7f91STakashi Iwai 		vol = sw = 0;
3762352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3763352f7f91STakashi Iwai 			struct nid_path *path;
3764c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3765352f7f91STakashi Iwai 			if (!path)
3766352f7f91STakashi Iwai 				continue;
3767352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3768352f7f91STakashi Iwai 			if (!vol)
3769352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
377099a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3771352f7f91STakashi Iwai 				multi = true;
377299a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
377399a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
377499a5592dSDavid Henningsson 					multi_cap_vol = true;
377599a5592dSDavid Henningsson 			}
3776352f7f91STakashi Iwai 			if (!sw)
3777352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
377899a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3779352f7f91STakashi Iwai 				multi = true;
378099a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
378199a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
378299a5592dSDavid Henningsson 					multi_cap_vol = true;
378399a5592dSDavid Henningsson 			}
3784352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3785352f7f91STakashi Iwai 				inv_dmic = true;
3786352f7f91STakashi Iwai 		}
3787352f7f91STakashi Iwai 
3788352f7f91STakashi Iwai 		if (!multi)
3789352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3790352f7f91STakashi Iwai 							inv_dmic);
3791ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3792352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3793352f7f91STakashi Iwai 		else
3794352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3795d13bd412STakashi Iwai 		if (err < 0)
3796071c73adSTakashi Iwai 			return err;
3797071c73adSTakashi Iwai 	}
3798071c73adSTakashi Iwai 
37991da177e4SLinus Torvalds 	return 0;
38001da177e4SLinus Torvalds }
38011da177e4SLinus Torvalds 
3802352f7f91STakashi Iwai /*
3803352f7f91STakashi Iwai  * add mic boosts if needed
3804352f7f91STakashi Iwai  */
38056f7c83afSTakashi Iwai 
38066f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
38076f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
38086f7c83afSTakashi Iwai 			    int dir, int idx)
38096f7c83afSTakashi Iwai {
38106f7c83afSTakashi Iwai 	unsigned int step;
38116f7c83afSTakashi Iwai 
38126f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
38136f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
38146f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
38156f7c83afSTakashi Iwai 		return false;
38166f7c83afSTakashi Iwai 
38176f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
38186f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
38196f7c83afSTakashi Iwai 	if (step < 0x20)
38206f7c83afSTakashi Iwai 		return false;
38216f7c83afSTakashi Iwai 	return true;
38226f7c83afSTakashi Iwai }
38236f7c83afSTakashi Iwai 
38246f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
38256f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
38266f7c83afSTakashi Iwai 				       struct nid_path *path)
38276f7c83afSTakashi Iwai {
38286f7c83afSTakashi Iwai 	unsigned int val = 0;
38296f7c83afSTakashi Iwai 	hda_nid_t nid;
38306f7c83afSTakashi Iwai 	int depth;
38316f7c83afSTakashi Iwai 
38326f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
38336f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
38346f7c83afSTakashi Iwai 			break;
38356f7c83afSTakashi Iwai 		nid = path->path[depth];
38366f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
38376f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
38386f7c83afSTakashi Iwai 			break;
38396f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
38406f7c83afSTakashi Iwai 					   path->idx[depth])) {
38416f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
38426f7c83afSTakashi Iwai 						  HDA_INPUT);
38436f7c83afSTakashi Iwai 			break;
38446f7c83afSTakashi Iwai 		}
38456f7c83afSTakashi Iwai 	}
38466f7c83afSTakashi Iwai 
38476f7c83afSTakashi Iwai 	return val;
38486f7c83afSTakashi Iwai }
38496f7c83afSTakashi Iwai 
3850352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3851352f7f91STakashi Iwai {
3852352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3853352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
38546f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3855a35bd1e3STakashi Iwai 	int i;
3856352f7f91STakashi Iwai 
38576f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
38586f7c83afSTakashi Iwai 		return 0;
38596f7c83afSTakashi Iwai 
38606f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3861352f7f91STakashi Iwai 		struct nid_path *path;
3862352f7f91STakashi Iwai 		unsigned int val;
38636f7c83afSTakashi Iwai 		int idx;
3864975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3865352f7f91STakashi Iwai 
38666f7c83afSTakashi Iwai 		idx = imux->items[i].index;
38676f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
386802aba550SDavid Henningsson 			continue;
386902aba550SDavid Henningsson 
38706f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
38711799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
38726f7c83afSTakashi Iwai 			continue;
38736f7c83afSTakashi Iwai 
38746f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
38756f7c83afSTakashi Iwai 		if (!path)
38766f7c83afSTakashi Iwai 			continue;
38776f7c83afSTakashi Iwai 
38786f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
38796f7c83afSTakashi Iwai 		if (!val)
38806f7c83afSTakashi Iwai 			continue;
38816f7c83afSTakashi Iwai 
38826f7c83afSTakashi Iwai 		/* create a boost control */
3883352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
38846f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3885a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3886a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3887a35bd1e3STakashi Iwai 			return -ENOMEM;
3888352f7f91STakashi Iwai 
3889352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3890352f7f91STakashi Iwai 	}
3891352f7f91STakashi Iwai 	return 0;
3892352f7f91STakashi Iwai }
3893352f7f91STakashi Iwai 
38947cdf8c49STakashi Iwai #ifdef CONFIG_SND_HDA_GENERIC_LEDS
3895352f7f91STakashi Iwai /*
389615509b63STakashi Iwai  * vmaster mute LED hook helpers
389715509b63STakashi Iwai  */
389815509b63STakashi Iwai 
389915509b63STakashi Iwai static int create_mute_led_cdev(struct hda_codec *codec,
390015509b63STakashi Iwai 				int (*callback)(struct led_classdev *,
390115509b63STakashi Iwai 						enum led_brightness),
390215509b63STakashi Iwai 				bool micmute)
390315509b63STakashi Iwai {
390415509b63STakashi Iwai 	struct led_classdev *cdev;
390515509b63STakashi Iwai 
390615509b63STakashi Iwai 	cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
390715509b63STakashi Iwai 	if (!cdev)
390815509b63STakashi Iwai 		return -ENOMEM;
390915509b63STakashi Iwai 
391015509b63STakashi Iwai 	cdev->name = micmute ? "hda::micmute" : "hda::mute";
391115509b63STakashi Iwai 	cdev->max_brightness = 1;
391215509b63STakashi Iwai 	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
391315509b63STakashi Iwai 	cdev->brightness_set_blocking = callback;
391415509b63STakashi Iwai 	cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE);
3915c9e272f9STakashi Iwai 	cdev->flags = LED_CORE_SUSPENDRESUME;
391615509b63STakashi Iwai 
391715509b63STakashi Iwai 	return devm_led_classdev_register(&codec->core.dev, cdev);
391815509b63STakashi Iwai }
391915509b63STakashi Iwai 
392015509b63STakashi Iwai static void vmaster_update_mute_led(void *private_data, int enabled)
392115509b63STakashi Iwai {
392215509b63STakashi Iwai 	ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
392315509b63STakashi Iwai }
392415509b63STakashi Iwai 
392515509b63STakashi Iwai /**
392615509b63STakashi Iwai  * snd_dha_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
392715509b63STakashi Iwai  * @codec: the HDA codec
392815509b63STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
392915509b63STakashi Iwai  */
393015509b63STakashi Iwai int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
393115509b63STakashi Iwai 				  int (*callback)(struct led_classdev *,
393215509b63STakashi Iwai 						  enum led_brightness))
393315509b63STakashi Iwai {
393415509b63STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
393515509b63STakashi Iwai 	int err;
393615509b63STakashi Iwai 
393715509b63STakashi Iwai 	if (callback) {
393815509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, false);
393915509b63STakashi Iwai 		if (err) {
394015509b63STakashi Iwai 			codec_warn(codec, "failed to create a mute LED cdev\n");
394115509b63STakashi Iwai 			return err;
394215509b63STakashi Iwai 		}
394315509b63STakashi Iwai 	}
394415509b63STakashi Iwai 
394515509b63STakashi Iwai 	if (spec->vmaster_mute.hook)
394615509b63STakashi Iwai 		codec_err(codec, "vmaster hook already present before cdev!\n");
394715509b63STakashi Iwai 
394815509b63STakashi Iwai 	spec->vmaster_mute.hook = vmaster_update_mute_led;
394915509b63STakashi Iwai 	spec->vmaster_mute_enum = 1;
395015509b63STakashi Iwai 	return 0;
395115509b63STakashi Iwai }
395215509b63STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
395315509b63STakashi Iwai 
395415509b63STakashi Iwai /*
3955f567b788STakashi Iwai  * mic mute LED hook helpers
3956f567b788STakashi Iwai  */
3957f567b788STakashi Iwai enum {
3958f567b788STakashi Iwai 	MICMUTE_LED_ON,
3959f567b788STakashi Iwai 	MICMUTE_LED_OFF,
3960f567b788STakashi Iwai 	MICMUTE_LED_FOLLOW_CAPTURE,
3961f567b788STakashi Iwai 	MICMUTE_LED_FOLLOW_MUTE,
3962f567b788STakashi Iwai };
3963f567b788STakashi Iwai 
3964f567b788STakashi Iwai static void call_micmute_led_update(struct hda_codec *codec)
3965f567b788STakashi Iwai {
3966f567b788STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3967f567b788STakashi Iwai 	unsigned int val;
3968f567b788STakashi Iwai 
3969f567b788STakashi Iwai 	switch (spec->micmute_led.led_mode) {
3970f567b788STakashi Iwai 	case MICMUTE_LED_ON:
3971f567b788STakashi Iwai 		val = 1;
3972f567b788STakashi Iwai 		break;
3973f567b788STakashi Iwai 	case MICMUTE_LED_OFF:
3974f567b788STakashi Iwai 		val = 0;
3975f567b788STakashi Iwai 		break;
3976f567b788STakashi Iwai 	case MICMUTE_LED_FOLLOW_CAPTURE:
3977c647f806STakashi Iwai 		val = !!spec->micmute_led.capture;
3978f567b788STakashi Iwai 		break;
3979f567b788STakashi Iwai 	case MICMUTE_LED_FOLLOW_MUTE:
3980f567b788STakashi Iwai 	default:
3981f567b788STakashi Iwai 		val = !spec->micmute_led.capture;
3982f567b788STakashi Iwai 		break;
3983f567b788STakashi Iwai 	}
3984f567b788STakashi Iwai 
3985f567b788STakashi Iwai 	if (val == spec->micmute_led.led_value)
3986f567b788STakashi Iwai 		return;
3987f567b788STakashi Iwai 	spec->micmute_led.led_value = val;
3988bf61c42aSTakashi Iwai 	ledtrig_audio_set(LED_AUDIO_MICMUTE,
3989bf61c42aSTakashi Iwai 			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
3990f567b788STakashi Iwai }
3991f567b788STakashi Iwai 
3992f567b788STakashi Iwai static void update_micmute_led(struct hda_codec *codec,
3993f567b788STakashi Iwai 			       struct snd_kcontrol *kcontrol,
3994f567b788STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
3995f567b788STakashi Iwai {
3996f567b788STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3997c647f806STakashi Iwai 	unsigned int mask;
3998f567b788STakashi Iwai 
3999f567b788STakashi Iwai 	if (spec->micmute_led.old_hook)
4000f567b788STakashi Iwai 		spec->micmute_led.old_hook(codec, kcontrol, ucontrol);
4001f567b788STakashi Iwai 
4002f567b788STakashi Iwai 	if (!ucontrol)
4003f567b788STakashi Iwai 		return;
4004c647f806STakashi Iwai 	mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4005c647f806STakashi Iwai 	if (!strcmp("Capture Switch", ucontrol->id.name)) {
4006f567b788STakashi Iwai 		/* TODO: How do I verify if it's a mono or stereo here? */
4007c647f806STakashi Iwai 		if (ucontrol->value.integer.value[0] ||
4008c647f806STakashi Iwai 		    ucontrol->value.integer.value[1])
4009c647f806STakashi Iwai 			spec->micmute_led.capture |= mask;
4010c647f806STakashi Iwai 		else
4011c647f806STakashi Iwai 			spec->micmute_led.capture &= ~mask;
4012f567b788STakashi Iwai 		call_micmute_led_update(codec);
4013f567b788STakashi Iwai 	}
4014f567b788STakashi Iwai }
4015f567b788STakashi Iwai 
4016f567b788STakashi Iwai static int micmute_led_mode_info(struct snd_kcontrol *kcontrol,
4017f567b788STakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
4018f567b788STakashi Iwai {
4019f567b788STakashi Iwai 	static const char * const texts[] = {
4020f567b788STakashi Iwai 		"On", "Off", "Follow Capture", "Follow Mute",
4021f567b788STakashi Iwai 	};
4022f567b788STakashi Iwai 
4023f567b788STakashi Iwai 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
4024f567b788STakashi Iwai }
4025f567b788STakashi Iwai 
4026f567b788STakashi Iwai static int micmute_led_mode_get(struct snd_kcontrol *kcontrol,
4027f567b788STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
4028f567b788STakashi Iwai {
4029f567b788STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4030f567b788STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4031f567b788STakashi Iwai 
4032f567b788STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode;
4033f567b788STakashi Iwai 	return 0;
4034f567b788STakashi Iwai }
4035f567b788STakashi Iwai 
4036f567b788STakashi Iwai static int micmute_led_mode_put(struct snd_kcontrol *kcontrol,
4037f567b788STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
4038f567b788STakashi Iwai {
4039f567b788STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4040f567b788STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4041f567b788STakashi Iwai 	unsigned int mode;
4042f567b788STakashi Iwai 
4043f567b788STakashi Iwai 	mode = ucontrol->value.enumerated.item[0];
4044f567b788STakashi Iwai 	if (mode > MICMUTE_LED_FOLLOW_MUTE)
4045f567b788STakashi Iwai 		mode = MICMUTE_LED_FOLLOW_MUTE;
4046f567b788STakashi Iwai 	if (mode == spec->micmute_led.led_mode)
4047f567b788STakashi Iwai 		return 0;
4048f567b788STakashi Iwai 	spec->micmute_led.led_mode = mode;
4049f567b788STakashi Iwai 	call_micmute_led_update(codec);
4050f567b788STakashi Iwai 	return 1;
4051f567b788STakashi Iwai }
4052f567b788STakashi Iwai 
4053f567b788STakashi Iwai static const struct snd_kcontrol_new micmute_led_mode_ctl = {
4054f567b788STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4055f567b788STakashi Iwai 	.name = "Mic Mute-LED Mode",
4056f567b788STakashi Iwai 	.info = micmute_led_mode_info,
4057f567b788STakashi Iwai 	.get = micmute_led_mode_get,
4058f567b788STakashi Iwai 	.put = micmute_led_mode_put,
4059f567b788STakashi Iwai };
4060f567b788STakashi Iwai 
4061fe1a1621STakashi Iwai /* Set up the capture sync hook for controlling the mic-mute LED */
4062fe1a1621STakashi Iwai static int add_micmute_led_hook(struct hda_codec *codec)
4063f567b788STakashi Iwai {
4064f567b788STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4065f567b788STakashi Iwai 
4066f567b788STakashi Iwai 	spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
4067f567b788STakashi Iwai 	spec->micmute_led.capture = 0;
4068f567b788STakashi Iwai 	spec->micmute_led.led_value = 0;
4069f567b788STakashi Iwai 	spec->micmute_led.old_hook = spec->cap_sync_hook;
4070f567b788STakashi Iwai 	spec->cap_sync_hook = update_micmute_led;
4071f567b788STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
4072f567b788STakashi Iwai 		return -ENOMEM;
4073c647f806STakashi Iwai 	return 0;
4074f567b788STakashi Iwai }
4075f567b788STakashi Iwai 
4076b3802783STakashi Iwai /**
40777cdf8c49STakashi Iwai  * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
40787cdf8c49STakashi Iwai  * @codec: the HDA codec
40797cdf8c49STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
40807cdf8c49STakashi Iwai  *
40817cdf8c49STakashi Iwai  * Called from the codec drivers for offering the mic mute LED controls.
40827cdf8c49STakashi Iwai  * This creates a LED classdev and sets up the cap_sync_hook that is called at
40837cdf8c49STakashi Iwai  * each time when the capture mixer switch changes.
40847cdf8c49STakashi Iwai  *
40857cdf8c49STakashi Iwai  * When NULL is passed to @callback, no classdev is created but only the
40867cdf8c49STakashi Iwai  * LED-trigger is set up.
40877cdf8c49STakashi Iwai  *
40887cdf8c49STakashi Iwai  * Returns 0 or a negative error.
40897cdf8c49STakashi Iwai  */
40907cdf8c49STakashi Iwai int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
40917cdf8c49STakashi Iwai 				     int (*callback)(struct led_classdev *,
40927cdf8c49STakashi Iwai 						     enum led_brightness))
40937cdf8c49STakashi Iwai {
40947cdf8c49STakashi Iwai 	int err;
40957cdf8c49STakashi Iwai 
40967cdf8c49STakashi Iwai 	if (callback) {
409715509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, true);
40987cdf8c49STakashi Iwai 		if (err) {
40997cdf8c49STakashi Iwai 			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
41007cdf8c49STakashi Iwai 			return err;
41017cdf8c49STakashi Iwai 		}
41027cdf8c49STakashi Iwai 	}
41037cdf8c49STakashi Iwai 
4104fe1a1621STakashi Iwai 	return add_micmute_led_hook(codec);
41057cdf8c49STakashi Iwai }
41067cdf8c49STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
41077cdf8c49STakashi Iwai #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
41087cdf8c49STakashi Iwai 
4109f567b788STakashi Iwai /*
4110352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
4111352f7f91STakashi Iwai  */
4112352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
4113352f7f91STakashi Iwai {
4114352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
41150c8c0f56STakashi Iwai 	struct nid_path *path;
4116352f7f91STakashi Iwai 	int i, nums;
41172c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
4118352f7f91STakashi Iwai 
41199ab0cb30STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a follower */
4120352f7f91STakashi Iwai 	nums = 0;
4121352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
41222c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
4123352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
4124352f7f91STakashi Iwai 		if (!dig_nid)
4125352f7f91STakashi Iwai 			continue;
41263ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
41270c8c0f56STakashi Iwai 		if (!path)
4128352f7f91STakashi Iwai 			continue;
41294e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
4130e1284af7STakashi Iwai 		path->active = true;
41316b275b14STakashi Iwai 		path->pin_fixed = true; /* no jack detection */
4132196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
41332c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
4134352f7f91STakashi Iwai 		if (!nums) {
4135352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
4136352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
4137352f7f91STakashi Iwai 		} else {
41389ab0cb30STakashi Iwai 			spec->multiout.follower_dig_outs = spec->follower_dig_outs;
41399ab0cb30STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1)
4140352f7f91STakashi Iwai 				break;
41419ab0cb30STakashi Iwai 			spec->follower_dig_outs[nums - 1] = dig_nid;
4142352f7f91STakashi Iwai 		}
4143352f7f91STakashi Iwai 		nums++;
4144352f7f91STakashi Iwai 	}
4145352f7f91STakashi Iwai 
4146352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
41472c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
41487639a06cSTakashi Iwai 		for_each_hda_codec_node(dig_nid, codec) {
4149352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
4150352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
4151352f7f91STakashi Iwai 				continue;
4152352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
4153352f7f91STakashi Iwai 				continue;
41542c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
4155352f7f91STakashi Iwai 			if (path) {
41564e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
4157352f7f91STakashi Iwai 				path->active = true;
41586b275b14STakashi Iwai 				path->pin_fixed = true; /* no jack */
4159352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
41602430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
41612c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
4162352f7f91STakashi Iwai 				break;
4163352f7f91STakashi Iwai 			}
4164352f7f91STakashi Iwai 		}
4165352f7f91STakashi Iwai 	}
4166352f7f91STakashi Iwai }
4167352f7f91STakashi Iwai 
41681da177e4SLinus Torvalds 
41691da177e4SLinus Torvalds /*
4170352f7f91STakashi Iwai  * input MUX handling
41711da177e4SLinus Torvalds  */
41721da177e4SLinus Torvalds 
4173352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
4174352f7f91STakashi Iwai 
4175352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
4176352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
4177352f7f91STakashi Iwai 		      unsigned int idx)
4178352f7f91STakashi Iwai {
4179352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4180352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
418155196fffSTakashi Iwai 	struct nid_path *old_path, *path;
4182352f7f91STakashi Iwai 
4183352f7f91STakashi Iwai 	imux = &spec->input_mux;
4184352f7f91STakashi Iwai 	if (!imux->num_items)
41851da177e4SLinus Torvalds 		return 0;
41861da177e4SLinus Torvalds 
4187352f7f91STakashi Iwai 	if (idx >= imux->num_items)
4188352f7f91STakashi Iwai 		idx = imux->num_items - 1;
4189352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
4190352f7f91STakashi Iwai 		return 0;
4191352f7f91STakashi Iwai 
419255196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
419355196fffSTakashi Iwai 	if (!old_path)
4194352f7f91STakashi Iwai 		return 0;
419555196fffSTakashi Iwai 	if (old_path->active)
419655196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
4197352f7f91STakashi Iwai 
4198352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
4199352f7f91STakashi Iwai 
4200967303daSTakashi Iwai 	if (spec->hp_mic)
4201967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
4202352f7f91STakashi Iwai 
4203352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4204352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
4205352f7f91STakashi Iwai 
4206c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
4207352f7f91STakashi Iwai 	if (!path)
4208352f7f91STakashi Iwai 		return 0;
4209352f7f91STakashi Iwai 	if (path->active)
4210352f7f91STakashi Iwai 		return 0;
4211352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
4212352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
42137fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
421455196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
42151da177e4SLinus Torvalds 	return 1;
42161da177e4SLinus Torvalds }
42171da177e4SLinus Torvalds 
4218e6feb5d0STakashi Iwai /* power up/down widgets in the all paths that match with the given NID
4219e6feb5d0STakashi Iwai  * as terminals (either start- or endpoint)
4220e6feb5d0STakashi Iwai  *
4221e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4222e6feb5d0STakashi Iwai  */
4223e6feb5d0STakashi Iwai static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
4224e6feb5d0STakashi Iwai 				int pin_state, int stream_state)
4225e6feb5d0STakashi Iwai {
4226e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4227e6feb5d0STakashi Iwai 	hda_nid_t last, changed = 0;
4228e6feb5d0STakashi Iwai 	struct nid_path *path;
4229e6feb5d0STakashi Iwai 	int n;
4230e6feb5d0STakashi Iwai 
4231a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, n, path) {
423281e43960SBob Copeland 		if (!path->depth)
423381e43960SBob Copeland 			continue;
4234e6feb5d0STakashi Iwai 		if (path->path[0] == nid ||
4235e6feb5d0STakashi Iwai 		    path->path[path->depth - 1] == nid) {
4236e6feb5d0STakashi Iwai 			bool pin_old = path->pin_enabled;
4237e6feb5d0STakashi Iwai 			bool stream_old = path->stream_enabled;
4238e6feb5d0STakashi Iwai 
4239e6feb5d0STakashi Iwai 			if (pin_state >= 0)
4240e6feb5d0STakashi Iwai 				path->pin_enabled = pin_state;
4241e6feb5d0STakashi Iwai 			if (stream_state >= 0)
4242e6feb5d0STakashi Iwai 				path->stream_enabled = stream_state;
42436b275b14STakashi Iwai 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
42446b275b14STakashi Iwai 			    || path->stream_enabled != stream_old) {
4245e6feb5d0STakashi Iwai 				last = path_power_update(codec, path, true);
4246e6feb5d0STakashi Iwai 				if (last)
4247e6feb5d0STakashi Iwai 					changed = last;
4248e6feb5d0STakashi Iwai 			}
4249e6feb5d0STakashi Iwai 		}
4250e6feb5d0STakashi Iwai 	}
4251e6feb5d0STakashi Iwai 	return changed;
4252e6feb5d0STakashi Iwai }
4253e6feb5d0STakashi Iwai 
4254d5ac0100STakashi Iwai /* check the jack status for power control */
4255d5ac0100STakashi Iwai static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4256d5ac0100STakashi Iwai {
4257d5ac0100STakashi Iwai 	if (!is_jack_detectable(codec, pin))
4258d5ac0100STakashi Iwai 		return true;
4259d5ac0100STakashi Iwai 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4260d5ac0100STakashi Iwai }
4261d5ac0100STakashi Iwai 
4262e6feb5d0STakashi Iwai /* power up/down the paths of the given pin according to the jack state;
4263e6feb5d0STakashi Iwai  * power = 0/1 : only power up/down if it matches with the jack state,
4264e6feb5d0STakashi Iwai  *       < 0   : force power up/down to follow the jack sate
4265e6feb5d0STakashi Iwai  *
4266e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4267e6feb5d0STakashi Iwai  */
4268e6feb5d0STakashi Iwai static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4269e6feb5d0STakashi Iwai 				    int power)
4270e6feb5d0STakashi Iwai {
4271e6feb5d0STakashi Iwai 	bool on;
4272e6feb5d0STakashi Iwai 
4273967b1307STakashi Iwai 	if (!codec->power_save_node)
4274e6feb5d0STakashi Iwai 		return 0;
4275e6feb5d0STakashi Iwai 
4276d5ac0100STakashi Iwai 	on = detect_pin_state(codec, pin);
4277d5ac0100STakashi Iwai 
4278e6feb5d0STakashi Iwai 	if (power >= 0 && on != power)
4279e6feb5d0STakashi Iwai 		return 0;
4280e6feb5d0STakashi Iwai 	return set_path_power(codec, pin, on, -1);
4281e6feb5d0STakashi Iwai }
4282e6feb5d0STakashi Iwai 
4283e6feb5d0STakashi Iwai static void pin_power_callback(struct hda_codec *codec,
4284e6feb5d0STakashi Iwai 			       struct hda_jack_callback *jack,
4285e6feb5d0STakashi Iwai 			       bool on)
4286e6feb5d0STakashi Iwai {
42872ebab40eSTakashi Iwai 	if (jack && jack->nid)
4288e6feb5d0STakashi Iwai 		sync_power_state_change(codec,
42892ebab40eSTakashi Iwai 					set_pin_power_jack(codec, jack->nid, on));
4290e6feb5d0STakashi Iwai }
4291e6feb5d0STakashi Iwai 
4292e6feb5d0STakashi Iwai /* callback only doing power up -- called at first */
4293e6feb5d0STakashi Iwai static void pin_power_up_callback(struct hda_codec *codec,
4294e6feb5d0STakashi Iwai 				  struct hda_jack_callback *jack)
4295e6feb5d0STakashi Iwai {
4296e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, true);
4297e6feb5d0STakashi Iwai }
4298e6feb5d0STakashi Iwai 
4299e6feb5d0STakashi Iwai /* callback only doing power down -- called at last */
4300e6feb5d0STakashi Iwai static void pin_power_down_callback(struct hda_codec *codec,
4301e6feb5d0STakashi Iwai 				    struct hda_jack_callback *jack)
4302e6feb5d0STakashi Iwai {
4303e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, false);
4304e6feb5d0STakashi Iwai }
4305e6feb5d0STakashi Iwai 
4306e6feb5d0STakashi Iwai /* set up the power up/down callbacks */
4307e6feb5d0STakashi Iwai static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4308e6feb5d0STakashi Iwai 			       const hda_nid_t *pins, bool on)
4309e6feb5d0STakashi Iwai {
4310e6feb5d0STakashi Iwai 	int i;
4311e6feb5d0STakashi Iwai 	hda_jack_callback_fn cb =
4312e6feb5d0STakashi Iwai 		on ? pin_power_up_callback : pin_power_down_callback;
4313e6feb5d0STakashi Iwai 
4314e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++) {
4315e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4316e6feb5d0STakashi Iwai 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4317e6feb5d0STakashi Iwai 		else
4318e6feb5d0STakashi Iwai 			set_path_power(codec, pins[i], true, -1);
4319e6feb5d0STakashi Iwai 	}
4320e6feb5d0STakashi Iwai }
4321e6feb5d0STakashi Iwai 
4322e6feb5d0STakashi Iwai /* enabled power callback to each available I/O pin with jack detections;
4323e6feb5d0STakashi Iwai  * the digital I/O pins are excluded because of the unreliable detectsion
4324e6feb5d0STakashi Iwai  */
4325e6feb5d0STakashi Iwai static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4326e6feb5d0STakashi Iwai {
4327e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4328e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4329e6feb5d0STakashi Iwai 	int i;
4330e6feb5d0STakashi Iwai 
4331967b1307STakashi Iwai 	if (!codec->power_save_node)
4332e6feb5d0STakashi Iwai 		return;
4333e6feb5d0STakashi Iwai 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4334e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4335e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4336e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4337e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4338e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4339e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4340e6feb5d0STakashi Iwai }
4341e6feb5d0STakashi Iwai 
4342e6feb5d0STakashi Iwai /* sync path power up/down with the jack states of given pins */
4343e6feb5d0STakashi Iwai static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4344e6feb5d0STakashi Iwai 				const hda_nid_t *pins)
4345e6feb5d0STakashi Iwai {
4346e6feb5d0STakashi Iwai 	int i;
4347e6feb5d0STakashi Iwai 
4348e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++)
4349e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4350e6feb5d0STakashi Iwai 			set_pin_power_jack(codec, pins[i], -1);
4351e6feb5d0STakashi Iwai }
4352e6feb5d0STakashi Iwai 
4353e6feb5d0STakashi Iwai /* sync path power up/down with pins; called at init and resume */
4354e6feb5d0STakashi Iwai static void sync_all_pin_power_ctls(struct hda_codec *codec)
4355e6feb5d0STakashi Iwai {
4356e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4357e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4358e6feb5d0STakashi Iwai 	int i;
4359e6feb5d0STakashi Iwai 
4360967b1307STakashi Iwai 	if (!codec->power_save_node)
4361e6feb5d0STakashi Iwai 		return;
4362e6feb5d0STakashi Iwai 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4363e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4364e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4365e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4366e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4367e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4368e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4369e6feb5d0STakashi Iwai }
43701da177e4SLinus Torvalds 
43715ccf835cSTakashi Iwai /* add fake paths if not present yet */
43725ccf835cSTakashi Iwai static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
43735ccf835cSTakashi Iwai 			   int num_pins, const hda_nid_t *pins)
43745ccf835cSTakashi Iwai {
43755ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
43765ccf835cSTakashi Iwai 	struct nid_path *path;
43775ccf835cSTakashi Iwai 	int i;
43785ccf835cSTakashi Iwai 
43795ccf835cSTakashi Iwai 	for (i = 0; i < num_pins; i++) {
43805ccf835cSTakashi Iwai 		if (!pins[i])
43815ccf835cSTakashi Iwai 			break;
43825ccf835cSTakashi Iwai 		if (get_nid_path(codec, nid, pins[i], 0))
43835ccf835cSTakashi Iwai 			continue;
43845ccf835cSTakashi Iwai 		path = snd_array_new(&spec->paths);
43855ccf835cSTakashi Iwai 		if (!path)
43865ccf835cSTakashi Iwai 			return -ENOMEM;
43875ccf835cSTakashi Iwai 		memset(path, 0, sizeof(*path));
43885ccf835cSTakashi Iwai 		path->depth = 2;
43895ccf835cSTakashi Iwai 		path->path[0] = nid;
43905ccf835cSTakashi Iwai 		path->path[1] = pins[i];
43915ccf835cSTakashi Iwai 		path->active = true;
43925ccf835cSTakashi Iwai 	}
43935ccf835cSTakashi Iwai 	return 0;
43945ccf835cSTakashi Iwai }
43955ccf835cSTakashi Iwai 
43965ccf835cSTakashi Iwai /* create fake paths to all outputs from beep */
43975ccf835cSTakashi Iwai static int add_fake_beep_paths(struct hda_codec *codec)
43985ccf835cSTakashi Iwai {
43995ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
44005ccf835cSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
44015ccf835cSTakashi Iwai 	hda_nid_t nid = spec->beep_nid;
44025ccf835cSTakashi Iwai 	int err;
44035ccf835cSTakashi Iwai 
4404967b1307STakashi Iwai 	if (!codec->power_save_node || !nid)
44055ccf835cSTakashi Iwai 		return 0;
44065ccf835cSTakashi Iwai 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
44075ccf835cSTakashi Iwai 	if (err < 0)
44085ccf835cSTakashi Iwai 		return err;
44095ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
44105ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
44115ccf835cSTakashi Iwai 		if (err < 0)
44125ccf835cSTakashi Iwai 			return err;
44135ccf835cSTakashi Iwai 	}
44145ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
44155ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
44165ccf835cSTakashi Iwai 				     cfg->speaker_pins);
44175ccf835cSTakashi Iwai 		if (err < 0)
44185ccf835cSTakashi Iwai 			return err;
44195ccf835cSTakashi Iwai 	}
44205ccf835cSTakashi Iwai 	return 0;
44215ccf835cSTakashi Iwai }
44225ccf835cSTakashi Iwai 
44235ccf835cSTakashi Iwai /* power up/down beep widget and its output paths */
44245ccf835cSTakashi Iwai static void beep_power_hook(struct hda_beep *beep, bool on)
44255ccf835cSTakashi Iwai {
44265ccf835cSTakashi Iwai 	set_path_power(beep->codec, beep->nid, -1, on);
44275ccf835cSTakashi Iwai }
44285ccf835cSTakashi Iwai 
44296b275b14STakashi Iwai /**
44306b275b14STakashi Iwai  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
44316b275b14STakashi Iwai  * @codec: the HDA codec
44326b275b14STakashi Iwai  * @pin: NID of pin to fix
44336b275b14STakashi Iwai  */
44346b275b14STakashi Iwai int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
44356b275b14STakashi Iwai {
44366b275b14STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
44376b275b14STakashi Iwai 	struct nid_path *path;
44386b275b14STakashi Iwai 
44396b275b14STakashi Iwai 	path = snd_array_new(&spec->paths);
44406b275b14STakashi Iwai 	if (!path)
44416b275b14STakashi Iwai 		return -ENOMEM;
44426b275b14STakashi Iwai 	memset(path, 0, sizeof(*path));
44436b275b14STakashi Iwai 	path->depth = 1;
44446b275b14STakashi Iwai 	path->path[0] = pin;
44456b275b14STakashi Iwai 	path->active = true;
44466b275b14STakashi Iwai 	path->pin_fixed = true;
44476b275b14STakashi Iwai 	path->stream_enabled = true;
44486b275b14STakashi Iwai 	return 0;
44496b275b14STakashi Iwai }
44506b275b14STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
44516b275b14STakashi Iwai 
44521da177e4SLinus Torvalds /*
4453352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
44541da177e4SLinus Torvalds  */
4455352f7f91STakashi Iwai 
4456352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
4457caf3c043SMichał Mirosław static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
44581da177e4SLinus Torvalds {
445960ea8ca2STakashi Iwai 	int i;
446060ea8ca2STakashi Iwai 	bool present = false;
44611da177e4SLinus Torvalds 
4462352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4463352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4464352f7f91STakashi Iwai 		if (!nid)
4465352f7f91STakashi Iwai 			break;
44660b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
44670b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
44680b4df931STakashi Iwai 			continue;
446960ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
447060ea8ca2STakashi Iwai 			present = true;
44711da177e4SLinus Torvalds 	}
4472352f7f91STakashi Iwai 	return present;
44731da177e4SLinus Torvalds }
44741da177e4SLinus Torvalds 
4475352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
4476caf3c043SMichał Mirosław static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
4477e80c60f3STakashi Iwai 			int *paths, bool mute)
44781da177e4SLinus Torvalds {
4479352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4480352f7f91STakashi Iwai 	int i;
44811da177e4SLinus Torvalds 
4482352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4483352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4484967303daSTakashi Iwai 		unsigned int val, oldval;
4485352f7f91STakashi Iwai 		if (!nid)
4486352f7f91STakashi Iwai 			break;
44877eebffd3STakashi Iwai 
4488e6feb5d0STakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4489e6feb5d0STakashi Iwai 		if (oldval & PIN_IN)
4490e6feb5d0STakashi Iwai 			continue; /* no mute for inputs */
4491e6feb5d0STakashi Iwai 
44927eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
4493e80c60f3STakashi Iwai 			struct nid_path *path;
4494e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
4495e80c60f3STakashi Iwai 
4496e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4497e80c60f3STakashi Iwai 			if (!path)
4498e80c60f3STakashi Iwai 				continue;
4499e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4500e80c60f3STakashi Iwai 			if (!mute_nid)
4501e80c60f3STakashi Iwai 				continue;
45027eebffd3STakashi Iwai 			if (mute)
4503e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
45047eebffd3STakashi Iwai 			else
4505e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
45067eebffd3STakashi Iwai 			continue;
4507e6feb5d0STakashi Iwai 		} else {
4508352f7f91STakashi Iwai 			/* don't reset VREF value in case it's controlling
4509352f7f91STakashi Iwai 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4510352f7f91STakashi Iwai 			 */
45112c12c30dSTakashi Iwai 			if (spec->keep_vref_in_automute)
4512967303daSTakashi Iwai 				val = oldval & ~PIN_HP;
45132c12c30dSTakashi Iwai 			else
4514352f7f91STakashi Iwai 				val = 0;
45152c12c30dSTakashi Iwai 			if (!mute)
4516967303daSTakashi Iwai 				val |= oldval;
4517e6feb5d0STakashi Iwai 			/* here we call update_pin_ctl() so that the pinctl is
4518e6feb5d0STakashi Iwai 			 * changed without changing the pinctl target value;
4519e6feb5d0STakashi Iwai 			 * the original target value will be still referred at
4520e6feb5d0STakashi Iwai 			 * the init / resume again
45212c12c30dSTakashi Iwai 			 */
45222c12c30dSTakashi Iwai 			update_pin_ctl(codec, nid, val);
4523e6feb5d0STakashi Iwai 		}
4524e6feb5d0STakashi Iwai 
4525d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
4526967b1307STakashi Iwai 		if (codec->power_save_node) {
4527e6feb5d0STakashi Iwai 			bool on = !mute;
4528e6feb5d0STakashi Iwai 			if (on)
4529d5ac0100STakashi Iwai 				on = detect_pin_state(codec, nid);
4530e6feb5d0STakashi Iwai 			set_path_power(codec, nid, on, -1);
4531e6feb5d0STakashi Iwai 		}
4532352f7f91STakashi Iwai 	}
4533352f7f91STakashi Iwai }
45341da177e4SLinus Torvalds 
4535dda42bd0STakashi Iwai /**
4536dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
4537dda42bd0STakashi Iwai  * @codec: the HDA codec
4538dda42bd0STakashi Iwai  *
4539dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
4540dda42bd0STakashi Iwai  */
45415d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
4542352f7f91STakashi Iwai {
4543352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4544e80c60f3STakashi Iwai 	int *paths;
4545352f7f91STakashi Iwai 	int on;
4546352f7f91STakashi Iwai 
4547352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
4548352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
4549352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
4550352f7f91STakashi Iwai 	 */
4551e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4552e80c60f3STakashi Iwai 		paths = spec->out_paths;
4553e80c60f3STakashi Iwai 	else
4554e80c60f3STakashi Iwai 		paths = spec->hp_paths;
4555352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4556e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4557352f7f91STakashi Iwai 
4558352f7f91STakashi Iwai 	if (!spec->automute_speaker)
4559352f7f91STakashi Iwai 		on = 0;
4560352f7f91STakashi Iwai 	else
4561352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
4562352f7f91STakashi Iwai 	on |= spec->master_mute;
456347b9ddb8STakashi Iwai 	spec->speaker_muted = on;
4564e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4565e80c60f3STakashi Iwai 		paths = spec->out_paths;
4566e80c60f3STakashi Iwai 	else
4567e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
4568352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4569e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
4570352f7f91STakashi Iwai 
4571352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
4572352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4573352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4574352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4575352f7f91STakashi Iwai 		return;
4576352f7f91STakashi Iwai 	if (!spec->automute_lo)
4577352f7f91STakashi Iwai 		on = 0;
4578352f7f91STakashi Iwai 	else
4579352f7f91STakashi Iwai 		on = spec->hp_jack_present;
4580352f7f91STakashi Iwai 	on |= spec->master_mute;
458147b9ddb8STakashi Iwai 	spec->line_out_muted = on;
4582e80c60f3STakashi Iwai 	paths = spec->out_paths;
4583352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4584e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
4585352f7f91STakashi Iwai }
45862698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4587352f7f91STakashi Iwai 
4588352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
4589352f7f91STakashi Iwai {
4590352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4591352f7f91STakashi Iwai 	if (spec->automute_hook)
4592352f7f91STakashi Iwai 		spec->automute_hook(codec);
4593352f7f91STakashi Iwai 	else
45945d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
45957eebffd3STakashi Iwai 
45969ab0cb30STakashi Iwai 	/* sync the whole vmaster followers to reflect the new auto-mute status */
45977eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
45987eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4599352f7f91STakashi Iwai }
4600352f7f91STakashi Iwai 
4601dda42bd0STakashi Iwai /**
4602dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4603dda42bd0STakashi Iwai  * @codec: the HDA codec
4604dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4605dda42bd0STakashi Iwai  */
46061a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
46071a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4608352f7f91STakashi Iwai {
4609352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
461092603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
461192603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4612352f7f91STakashi Iwai 
461392603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
461492603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
461592603c59STakashi Iwai 		pins++;
461692603c59STakashi Iwai 		num_pins--;
461792603c59STakashi Iwai 	}
461892603c59STakashi Iwai 
461992603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4620352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4621352f7f91STakashi Iwai 		return;
4622352f7f91STakashi Iwai 	call_update_outputs(codec);
4623352f7f91STakashi Iwai }
46242698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4625352f7f91STakashi Iwai 
4626dda42bd0STakashi Iwai /**
4627dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4628dda42bd0STakashi Iwai  * @codec: the HDA codec
4629dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4630dda42bd0STakashi Iwai  */
46311a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
46321a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4633352f7f91STakashi Iwai {
4634352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4635352f7f91STakashi Iwai 
4636352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4637352f7f91STakashi Iwai 		return;
4638352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4639352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4640352f7f91STakashi Iwai 		return;
4641352f7f91STakashi Iwai 
4642352f7f91STakashi Iwai 	spec->line_jack_present =
4643352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4644352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4645352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4646352f7f91STakashi Iwai 		return;
4647352f7f91STakashi Iwai 	call_update_outputs(codec);
4648352f7f91STakashi Iwai }
46492698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4650352f7f91STakashi Iwai 
4651dda42bd0STakashi Iwai /**
4652dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4653dda42bd0STakashi Iwai  * @codec: the HDA codec
4654dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4655dda42bd0STakashi Iwai  */
46561a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
46571a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4658352f7f91STakashi Iwai {
4659352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4660352f7f91STakashi Iwai 	int i;
4661352f7f91STakashi Iwai 
4662352f7f91STakashi Iwai 	if (!spec->auto_mic)
4663352f7f91STakashi Iwai 		return;
4664352f7f91STakashi Iwai 
4665352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
46660b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
46670b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
46680b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
46690b4df931STakashi Iwai 			continue;
467060ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4671352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4672352f7f91STakashi Iwai 			return;
4673352f7f91STakashi Iwai 		}
4674352f7f91STakashi Iwai 	}
4675352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
46761da177e4SLinus Torvalds }
46772698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
46781da177e4SLinus Torvalds 
467977afe0e9STakashi Iwai /* call appropriate hooks */
46801a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
46811a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
468277afe0e9STakashi Iwai {
468377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
468477afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
468577afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
468677afe0e9STakashi Iwai 	else
468777afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
468877afe0e9STakashi Iwai }
468977afe0e9STakashi Iwai 
469077afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
46911a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
469277afe0e9STakashi Iwai {
469377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
469477afe0e9STakashi Iwai 	if (spec->line_automute_hook)
469577afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
469677afe0e9STakashi Iwai 	else
469777afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
469877afe0e9STakashi Iwai }
469977afe0e9STakashi Iwai 
470077afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
47011a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
470277afe0e9STakashi Iwai {
470377afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
470477afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
470577afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
470677afe0e9STakashi Iwai 	else
470777afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
470877afe0e9STakashi Iwai }
470977afe0e9STakashi Iwai 
4710963afde9STakashi Iwai /* update jack retasking */
4711963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4712963afde9STakashi Iwai {
4713963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4714963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4715963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4716963afde9STakashi Iwai }
4717963afde9STakashi Iwai 
47181da177e4SLinus Torvalds /*
4719352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
47201da177e4SLinus Torvalds  */
4721352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4722352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4723352f7f91STakashi Iwai {
4724352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4725352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4726352f7f91STakashi Iwai 	static const char * const texts3[] = {
4727352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
47281da177e4SLinus Torvalds 	};
47291da177e4SLinus Torvalds 
4730352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4731352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4732352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4733352f7f91STakashi Iwai }
4734352f7f91STakashi Iwai 
4735352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4736352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4737352f7f91STakashi Iwai {
4738352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4739352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4740352f7f91STakashi Iwai 	unsigned int val = 0;
4741352f7f91STakashi Iwai 	if (spec->automute_speaker)
4742352f7f91STakashi Iwai 		val++;
4743352f7f91STakashi Iwai 	if (spec->automute_lo)
4744352f7f91STakashi Iwai 		val++;
4745352f7f91STakashi Iwai 
4746352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4747352f7f91STakashi Iwai 	return 0;
4748352f7f91STakashi Iwai }
4749352f7f91STakashi Iwai 
4750352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4751352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4752352f7f91STakashi Iwai {
4753352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4754352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4755352f7f91STakashi Iwai 
4756352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4757352f7f91STakashi Iwai 	case 0:
4758352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4759352f7f91STakashi Iwai 			return 0;
4760352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4761352f7f91STakashi Iwai 		spec->automute_lo = 0;
4762352f7f91STakashi Iwai 		break;
4763352f7f91STakashi Iwai 	case 1:
4764352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4765352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4766352f7f91STakashi Iwai 				return 0;
4767352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4768352f7f91STakashi Iwai 			spec->automute_lo = 0;
4769352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4770352f7f91STakashi Iwai 			if (spec->automute_lo)
4771352f7f91STakashi Iwai 				return 0;
4772352f7f91STakashi Iwai 			spec->automute_lo = 1;
4773352f7f91STakashi Iwai 		} else
4774352f7f91STakashi Iwai 			return -EINVAL;
4775352f7f91STakashi Iwai 		break;
4776352f7f91STakashi Iwai 	case 2:
4777352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4778352f7f91STakashi Iwai 			return -EINVAL;
4779352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4780352f7f91STakashi Iwai 			return 0;
4781352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4782352f7f91STakashi Iwai 		spec->automute_lo = 1;
4783352f7f91STakashi Iwai 		break;
4784352f7f91STakashi Iwai 	default:
4785352f7f91STakashi Iwai 		return -EINVAL;
4786352f7f91STakashi Iwai 	}
4787352f7f91STakashi Iwai 	call_update_outputs(codec);
4788352f7f91STakashi Iwai 	return 1;
4789352f7f91STakashi Iwai }
4790352f7f91STakashi Iwai 
4791352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4792352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4793352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4794352f7f91STakashi Iwai 	.info = automute_mode_info,
4795352f7f91STakashi Iwai 	.get = automute_mode_get,
4796352f7f91STakashi Iwai 	.put = automute_mode_put,
4797352f7f91STakashi Iwai };
4798352f7f91STakashi Iwai 
4799352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4800352f7f91STakashi Iwai {
4801352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4802352f7f91STakashi Iwai 
480312c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4804352f7f91STakashi Iwai 		return -ENOMEM;
4805352f7f91STakashi Iwai 	return 0;
4806352f7f91STakashi Iwai }
4807352f7f91STakashi Iwai 
4808352f7f91STakashi Iwai /*
4809352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4810352f7f91STakashi Iwai  * Set up appropriately if really supported
4811352f7f91STakashi Iwai  */
4812352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4813352f7f91STakashi Iwai {
4814352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4815352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4816352f7f91STakashi Iwai 	int present = 0;
4817352f7f91STakashi Iwai 	int i, err;
4818352f7f91STakashi Iwai 
4819f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4820f72706beSTakashi Iwai 		return 0;
4821f72706beSTakashi Iwai 
4822352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4823352f7f91STakashi Iwai 		present++;
4824352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4825352f7f91STakashi Iwai 		present++;
4826352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4827352f7f91STakashi Iwai 		present++;
4828352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4829352f7f91STakashi Iwai 		return 0;
4830352f7f91STakashi Iwai 
4831352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4832352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4833352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4834352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4835352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4836352f7f91STakashi Iwai 	}
4837352f7f91STakashi Iwai 
4838352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4839352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4840352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4841352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4842352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4843352f7f91STakashi Iwai 	}
4844352f7f91STakashi Iwai 
4845352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4846352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4847352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4848352f7f91STakashi Iwai 			continue;
48494e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
485062f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
485177afe0e9STakashi Iwai 						    call_hp_automute);
4852352f7f91STakashi Iwai 		spec->detect_hp = 1;
4853352f7f91STakashi Iwai 	}
4854352f7f91STakashi Iwai 
4855352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4856352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4857352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4858352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4859352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4860352f7f91STakashi Iwai 					continue;
48614e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4862352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
486377afe0e9STakashi Iwai 								    call_line_automute);
4864352f7f91STakashi Iwai 				spec->detect_lo = 1;
4865352f7f91STakashi Iwai 			}
4866352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4867352f7f91STakashi Iwai 	}
4868352f7f91STakashi Iwai 
4869352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4870352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4871352f7f91STakashi Iwai 
4872352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4873352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4874352f7f91STakashi Iwai 
4875352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4876352f7f91STakashi Iwai 		/* create a control for automute mode */
4877352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4878352f7f91STakashi Iwai 		if (err < 0)
4879352f7f91STakashi Iwai 			return err;
4880352f7f91STakashi Iwai 	}
4881352f7f91STakashi Iwai 	return 0;
4882352f7f91STakashi Iwai }
4883352f7f91STakashi Iwai 
4884352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4885352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4886352f7f91STakashi Iwai {
4887352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4888352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4889352f7f91STakashi Iwai 	int i;
4890352f7f91STakashi Iwai 
4891352f7f91STakashi Iwai 	imux = &spec->input_mux;
4892352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4893352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4894352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4895352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4896352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4897352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4898352f7f91STakashi Iwai 	}
4899352f7f91STakashi Iwai 
4900352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4901352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4902352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4903352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
490477afe0e9STakashi Iwai 						    call_mic_autoswitch);
4905352f7f91STakashi Iwai 	return true;
4906352f7f91STakashi Iwai }
4907352f7f91STakashi Iwai 
4908352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4909352f7f91STakashi Iwai {
4910352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4911352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4912352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4913352f7f91STakashi Iwai }
4914352f7f91STakashi Iwai 
4915352f7f91STakashi Iwai /*
4916352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4917352f7f91STakashi Iwai  * Set up if really supported
4918352f7f91STakashi Iwai  */
4919352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4920352f7f91STakashi Iwai {
4921352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4922352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4923352f7f91STakashi Iwai 	unsigned int types;
4924352f7f91STakashi Iwai 	int i, num_pins;
4925352f7f91STakashi Iwai 
4926d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4927d12daf6fSTakashi Iwai 		return 0;
4928d12daf6fSTakashi Iwai 
4929352f7f91STakashi Iwai 	types = 0;
4930352f7f91STakashi Iwai 	num_pins = 0;
4931352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4932352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4933352f7f91STakashi Iwai 		unsigned int attr;
4934352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4935352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4936352f7f91STakashi Iwai 		if (types & (1 << attr))
4937352f7f91STakashi Iwai 			return 0; /* already occupied */
4938352f7f91STakashi Iwai 		switch (attr) {
4939352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4940352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4941352f7f91STakashi Iwai 				return 0; /* invalid type */
4942352f7f91STakashi Iwai 			break;
4943352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4944352f7f91STakashi Iwai 			return 0; /* invalid entry */
4945352f7f91STakashi Iwai 		default:
4946352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4947352f7f91STakashi Iwai 				return 0; /* invalid type */
4948352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4949352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4950352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4951352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4952352f7f91STakashi Iwai 				return 0; /* no unsol support */
4953352f7f91STakashi Iwai 			break;
4954352f7f91STakashi Iwai 		}
4955352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4956352f7f91STakashi Iwai 			return 0;
4957352f7f91STakashi Iwai 		types |= (1 << attr);
4958352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4959352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4960352f7f91STakashi Iwai 		num_pins++;
4961352f7f91STakashi Iwai 	}
4962352f7f91STakashi Iwai 
4963352f7f91STakashi Iwai 	if (num_pins < 2)
4964352f7f91STakashi Iwai 		return 0;
4965352f7f91STakashi Iwai 
4966352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4967352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4968352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4969352f7f91STakashi Iwai 	 */
4970352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4971352f7f91STakashi Iwai 	     compare_attr, NULL);
4972352f7f91STakashi Iwai 
4973352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4974352f7f91STakashi Iwai 		return 0;
4975352f7f91STakashi Iwai 
4976352f7f91STakashi Iwai 	spec->auto_mic = 1;
4977352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4978352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
49794e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4980352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4981352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4982352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4983352f7f91STakashi Iwai 
4984352f7f91STakashi Iwai 	return 0;
4985352f7f91STakashi Iwai }
4986352f7f91STakashi Iwai 
4987dda42bd0STakashi Iwai /**
4988dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4989dda42bd0STakashi Iwai  * into power down
4990dda42bd0STakashi Iwai  * @codec: the HDA codec
4991dda42bd0STakashi Iwai  * @nid: NID to evalute
4992dda42bd0STakashi Iwai  * @power_state: target power state
4993dda42bd0STakashi Iwai  */
4994dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
499555196fffSTakashi Iwai 						  hda_nid_t nid,
499655196fffSTakashi Iwai 						  unsigned int power_state)
499755196fffSTakashi Iwai {
4998b6c09b3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4999b6c09b3cSTakashi Iwai 
5000b6c09b3cSTakashi Iwai 	if (!spec->power_down_unused && !codec->power_save_node)
5001b6c09b3cSTakashi Iwai 		return power_state;
50027639a06cSTakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
500355196fffSTakashi Iwai 		return power_state;
500455196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
500555196fffSTakashi Iwai 		return power_state;
5006b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
500755196fffSTakashi Iwai 		return power_state;
500855196fffSTakashi Iwai 	return AC_PWRST_D3;
500955196fffSTakashi Iwai }
5010dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
501155196fffSTakashi Iwai 
5012ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
5013ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
5014ebb93c05STakashi Iwai {
5015ebb93c05STakashi Iwai 	int i, nums;
5016ebb93c05STakashi Iwai 	const hda_nid_t *conn;
5017ebb93c05STakashi Iwai 	bool has_amp;
5018ebb93c05STakashi Iwai 
5019ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
5020ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
5021ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
5022ebb93c05STakashi Iwai 		if (has_amp)
5023ef403edbSTakashi Iwai 			update_amp(codec, mix, HDA_INPUT, i,
5024ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
5025ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
5026ef403edbSTakashi Iwai 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
5027ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
5028ebb93c05STakashi Iwai 	}
5029ebb93c05STakashi Iwai }
5030352f7f91STakashi Iwai 
5031dda42bd0STakashi Iwai /**
5032e6feb5d0STakashi Iwai  * snd_hda_gen_stream_pm - Stream power management callback
5033e6feb5d0STakashi Iwai  * @codec: the HDA codec
5034e6feb5d0STakashi Iwai  * @nid: audio widget
5035e6feb5d0STakashi Iwai  * @on: power on/off flag
5036e6feb5d0STakashi Iwai  *
5037967b1307STakashi Iwai  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
5038e6feb5d0STakashi Iwai  */
5039e6feb5d0STakashi Iwai void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
5040e6feb5d0STakashi Iwai {
5041967b1307STakashi Iwai 	if (codec->power_save_node)
5042e6feb5d0STakashi Iwai 		set_path_power(codec, nid, -1, on);
5043e6feb5d0STakashi Iwai }
5044e6feb5d0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
5045e6feb5d0STakashi Iwai 
5046e6feb5d0STakashi Iwai /**
5047dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
5048dda42bd0STakashi Iwai  * set up the hda_gen_spec
5049dda42bd0STakashi Iwai  * @codec: the HDA codec
5050dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
50519eb413e5STakashi Iwai  *
50529eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
5053352f7f91STakashi Iwai  * or a negative error code
5054352f7f91STakashi Iwai  */
5055352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
50569eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
5057352f7f91STakashi Iwai {
5058352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5059352f7f91STakashi Iwai 	int err;
5060352f7f91STakashi Iwai 
50611c70a583STakashi Iwai 	parse_user_hints(codec);
50621c70a583STakashi Iwai 
5063e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
5064e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
5065e4a395e7STakashi Iwai 
50669eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
50679eb413e5STakashi Iwai 		spec->autocfg = *cfg;
50689eb413e5STakashi Iwai 		cfg = &spec->autocfg;
50699eb413e5STakashi Iwai 	}
50709eb413e5STakashi Iwai 
507198bd1115STakashi Iwai 	if (!spec->main_out_badness)
507298bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
507398bd1115STakashi Iwai 	if (!spec->extra_out_badness)
507498bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
507598bd1115STakashi Iwai 
50766fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
50776fc4cb97SDavid Henningsson 
5078352f7f91STakashi Iwai 	if (!cfg->line_outs) {
5079352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
5080352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
5081352f7f91STakashi Iwai 			spec->no_analog = 1;
5082352f7f91STakashi Iwai 			goto dig_only;
5083352f7f91STakashi Iwai 		}
5084c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
5085352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
5086352f7f91STakashi Iwai 	}
5087352f7f91STakashi Iwai 
5088352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
5089352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
5090352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
5091352f7f91STakashi Iwai 		/* use HP as primary out */
5092352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
5093352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
5094352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
5095352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
5096352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
5097352f7f91STakashi Iwai 		cfg->hp_outs = 0;
5098352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
5099352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
5100352f7f91STakashi Iwai 	}
5101352f7f91STakashi Iwai 
5102352f7f91STakashi Iwai 	err = parse_output_paths(codec);
5103352f7f91STakashi Iwai 	if (err < 0)
5104352f7f91STakashi Iwai 		return err;
5105352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
5106352f7f91STakashi Iwai 	if (err < 0)
5107352f7f91STakashi Iwai 		return err;
5108352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
5109352f7f91STakashi Iwai 	if (err < 0)
5110352f7f91STakashi Iwai 		return err;
5111352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
5112352f7f91STakashi Iwai 	if (err < 0)
5113352f7f91STakashi Iwai 		return err;
5114352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
5115352f7f91STakashi Iwai 	if (err < 0)
5116352f7f91STakashi Iwai 		return err;
511738cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
511838cf6f1aSTakashi Iwai 	if (err < 0)
511938cf6f1aSTakashi Iwai 		return err;
5120c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
5121c30aa7b2STakashi Iwai 	if (err < 0)
5122c30aa7b2STakashi Iwai 		return err;
5123967303daSTakashi Iwai 	err = create_hp_mic(codec);
5124352f7f91STakashi Iwai 	if (err < 0)
5125352f7f91STakashi Iwai 		return err;
5126352f7f91STakashi Iwai 	err = create_input_ctls(codec);
5127352f7f91STakashi Iwai 	if (err < 0)
5128352f7f91STakashi Iwai 		return err;
5129352f7f91STakashi Iwai 
5130e6feb5d0STakashi Iwai 	/* add power-down pin callbacks at first */
5131e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, false);
5132e6feb5d0STakashi Iwai 
5133a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
5134a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
5135a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
5136a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5137a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
5138a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
5139a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5140a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
5141352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
5142352f7f91STakashi Iwai 					  spec->const_channel_count);
5143352f7f91STakashi Iwai 
5144352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
5145352f7f91STakashi Iwai 	if (err < 0)
5146352f7f91STakashi Iwai 		return err;
5147352f7f91STakashi Iwai 
5148352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
5149352f7f91STakashi Iwai 	if (err < 0)
5150352f7f91STakashi Iwai 		return err;
5151352f7f91STakashi Iwai 
5152352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
5153352f7f91STakashi Iwai 	if (err < 0)
5154352f7f91STakashi Iwai 		return err;
5155352f7f91STakashi Iwai 
5156f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
5157f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
515874f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
515974f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
5160f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
5161f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
5162f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
5163f1e762ddSTakashi Iwai 		if (err < 0)
5164f1e762ddSTakashi Iwai 			return err;
5165f1e762ddSTakashi Iwai 	}
5166f1e762ddSTakashi Iwai 
5167f1e762ddSTakashi Iwai 
5168352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
5169352f7f91STakashi Iwai 	if (err < 0)
5170352f7f91STakashi Iwai 		return err;
5171352f7f91STakashi Iwai 
5172352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
5173352f7f91STakashi Iwai 	if (err < 0)
5174352f7f91STakashi Iwai 		return err;
5175352f7f91STakashi Iwai 
5176ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
5177ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
5178ced4cefcSTakashi Iwai 	 */
5179ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
5180ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
5181ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
5182ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
5183ced4cefcSTakashi Iwai 		if (err < 0)
5184ced4cefcSTakashi Iwai 			return err;
5185ced4cefcSTakashi Iwai 	}
5186ced4cefcSTakashi Iwai 
5187f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
5188978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
5189978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
5190978e77e7STakashi Iwai 						    cfg->line_out_pins);
5191978e77e7STakashi Iwai 			if (err < 0)
5192978e77e7STakashi Iwai 				return err;
5193978e77e7STakashi Iwai 		}
5194978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
5195978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
5196978e77e7STakashi Iwai 						    cfg->hp_pins);
5197978e77e7STakashi Iwai 			if (err < 0)
5198978e77e7STakashi Iwai 				return err;
5199978e77e7STakashi Iwai 		}
5200978e77e7STakashi Iwai 	}
5201978e77e7STakashi Iwai 
5202e6feb5d0STakashi Iwai 	/* add power-up pin callbacks at last */
5203e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, true);
5204e6feb5d0STakashi Iwai 
5205ebb93c05STakashi Iwai 	/* mute all aamix input initially */
5206ebb93c05STakashi Iwai 	if (spec->mixer_nid)
5207ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
5208ebb93c05STakashi Iwai 
5209352f7f91STakashi Iwai  dig_only:
5210352f7f91STakashi Iwai 	parse_digital(codec);
5211352f7f91STakashi Iwai 
521249fb1897STakashi Iwai 	if (spec->power_down_unused || codec->power_save_node) {
521324fef902STakashi Iwai 		if (!codec->power_filter)
521455196fffSTakashi Iwai 			codec->power_filter = snd_hda_gen_path_power_filter;
521549fb1897STakashi Iwai 		if (!codec->patch_ops.stream_pm)
521649fb1897STakashi Iwai 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
521749fb1897STakashi Iwai 	}
521855196fffSTakashi Iwai 
52197504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
52207504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
52217504b6cdSTakashi Iwai 		if (err < 0)
52227504b6cdSTakashi Iwai 			return err;
5223967b1307STakashi Iwai 		if (codec->beep && codec->power_save_node) {
52245ccf835cSTakashi Iwai 			err = add_fake_beep_paths(codec);
52255ccf835cSTakashi Iwai 			if (err < 0)
52265ccf835cSTakashi Iwai 				return err;
52275ccf835cSTakashi Iwai 			codec->beep->power_hook = beep_power_hook;
52285ccf835cSTakashi Iwai 		}
52297504b6cdSTakashi Iwai 	}
52307504b6cdSTakashi Iwai 
5231352f7f91STakashi Iwai 	return 1;
5232352f7f91STakashi Iwai }
52332698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
5234352f7f91STakashi Iwai 
5235352f7f91STakashi Iwai 
5236352f7f91STakashi Iwai /*
5237352f7f91STakashi Iwai  * Build control elements
5238352f7f91STakashi Iwai  */
5239352f7f91STakashi Iwai 
52409ab0cb30STakashi Iwai /* follower controls for virtual master */
52419ab0cb30STakashi Iwai static const char * const follower_pfxs[] = {
5242352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
5243352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
5244352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
5245ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
5246ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
524703ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
5248352f7f91STakashi Iwai 	NULL,
5249352f7f91STakashi Iwai };
5250352f7f91STakashi Iwai 
5251dda42bd0STakashi Iwai /**
5252dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
5253dda42bd0STakashi Iwai  * @codec: the HDA codec
5254dda42bd0STakashi Iwai  *
5255dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
5256dda42bd0STakashi Iwai  */
5257352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
5258352f7f91STakashi Iwai {
5259352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5260352f7f91STakashi Iwai 	int err;
5261352f7f91STakashi Iwai 
526236502d02STakashi Iwai 	if (spec->kctls.used) {
5263352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5264352f7f91STakashi Iwai 		if (err < 0)
5265352f7f91STakashi Iwai 			return err;
526636502d02STakashi Iwai 	}
5267352f7f91STakashi Iwai 
5268352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
5269352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
5270352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5271352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5272bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
5273352f7f91STakashi Iwai 		if (err < 0)
5274352f7f91STakashi Iwai 			return err;
5275352f7f91STakashi Iwai 		if (!spec->no_analog) {
5276352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
5277352f7f91STakashi Iwai 							    &spec->multiout);
5278352f7f91STakashi Iwai 			if (err < 0)
5279352f7f91STakashi Iwai 				return err;
5280352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
5281352f7f91STakashi Iwai 		}
5282352f7f91STakashi Iwai 	}
5283352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
5284352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5285352f7f91STakashi Iwai 		if (err < 0)
5286352f7f91STakashi Iwai 			return err;
5287352f7f91STakashi Iwai 	}
5288352f7f91STakashi Iwai 
5289352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
52907480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5291352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5292352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
52939ab0cb30STakashi Iwai 					  spec->vmaster_tlv, follower_pfxs,
5294352f7f91STakashi Iwai 					  "Playback Volume");
5295352f7f91STakashi Iwai 		if (err < 0)
5296352f7f91STakashi Iwai 			return err;
5297352f7f91STakashi Iwai 	}
52987480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5299352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5300352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
53019ab0cb30STakashi Iwai 					    NULL, follower_pfxs,
5302352f7f91STakashi Iwai 					    "Playback Switch",
5303352f7f91STakashi Iwai 					    true, &spec->vmaster_mute.sw_kctl);
5304352f7f91STakashi Iwai 		if (err < 0)
5305352f7f91STakashi Iwai 			return err;
5306b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
5307fd25a97aSTakashi Iwai 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
5308fd25a97aSTakashi Iwai 						 spec->vmaster_mute_enum);
5309b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5310b63eae0aSTakashi Iwai 		}
5311352f7f91STakashi Iwai 	}
5312352f7f91STakashi Iwai 
5313352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
5314352f7f91STakashi Iwai 
5315352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5316352f7f91STakashi Iwai 	if (err < 0)
5317352f7f91STakashi Iwai 		return err;
5318352f7f91STakashi Iwai 
5319352f7f91STakashi Iwai 	return 0;
5320352f7f91STakashi Iwai }
53212698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5322352f7f91STakashi Iwai 
5323352f7f91STakashi Iwai 
5324352f7f91STakashi Iwai /*
5325352f7f91STakashi Iwai  * PCM definitions
5326352f7f91STakashi Iwai  */
5327352f7f91STakashi Iwai 
5328e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5329e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
5330e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
5331e6b85f3cSTakashi Iwai 				   int action)
5332e6b85f3cSTakashi Iwai {
5333e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5334e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
5335e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5336e6b85f3cSTakashi Iwai }
5337e6b85f3cSTakashi Iwai 
5338ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5339ac2e8736STakashi Iwai 				  struct hda_codec *codec,
5340ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
5341ac2e8736STakashi Iwai 				  int action)
5342ac2e8736STakashi Iwai {
5343ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5344ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
5345ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5346ac2e8736STakashi Iwai }
5347ac2e8736STakashi Iwai 
5348352f7f91STakashi Iwai /*
5349352f7f91STakashi Iwai  * Analog playback callbacks
5350352f7f91STakashi Iwai  */
5351352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5352352f7f91STakashi Iwai 			     struct hda_codec *codec,
5353352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
5354352f7f91STakashi Iwai {
5355352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
535638cf6f1aSTakashi Iwai 	int err;
535738cf6f1aSTakashi Iwai 
535838cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
535938cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
536038cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
5361352f7f91STakashi Iwai 					     hinfo);
5362e6b85f3cSTakashi Iwai 	if (!err) {
536338cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5364e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5365e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
5366e6b85f3cSTakashi Iwai 	}
536738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
536838cf6f1aSTakashi Iwai 	return err;
5369352f7f91STakashi Iwai }
5370352f7f91STakashi Iwai 
5371352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
537297ec558aSTakashi Iwai 				struct hda_codec *codec,
537397ec558aSTakashi Iwai 				unsigned int stream_tag,
537497ec558aSTakashi Iwai 				unsigned int format,
537597ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
537697ec558aSTakashi Iwai {
5377352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5378e6b85f3cSTakashi Iwai 	int err;
5379e6b85f3cSTakashi Iwai 
5380e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5381352f7f91STakashi Iwai 					       stream_tag, format, substream);
5382e6b85f3cSTakashi Iwai 	if (!err)
5383e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5384e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
5385e6b85f3cSTakashi Iwai 	return err;
5386352f7f91STakashi Iwai }
538797ec558aSTakashi Iwai 
5388352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5389352f7f91STakashi Iwai 				struct hda_codec *codec,
5390352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
5391352f7f91STakashi Iwai {
5392352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5393e6b85f3cSTakashi Iwai 	int err;
5394e6b85f3cSTakashi Iwai 
5395e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5396e6b85f3cSTakashi Iwai 	if (!err)
5397e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5398e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
5399e6b85f3cSTakashi Iwai 	return err;
5400352f7f91STakashi Iwai }
5401352f7f91STakashi Iwai 
540238cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
540338cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
540438cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
540538cf6f1aSTakashi Iwai {
540638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
540738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
540838cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5409e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5410e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
541138cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
541238cf6f1aSTakashi Iwai 	return 0;
541338cf6f1aSTakashi Iwai }
541438cf6f1aSTakashi Iwai 
5415ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5416ac2e8736STakashi Iwai 			    struct hda_codec *codec,
5417ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
5418ac2e8736STakashi Iwai {
5419ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5420ac2e8736STakashi Iwai 	return 0;
5421ac2e8736STakashi Iwai }
5422ac2e8736STakashi Iwai 
5423ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5424ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5425ac2e8736STakashi Iwai 			       unsigned int stream_tag,
5426ac2e8736STakashi Iwai 			       unsigned int format,
5427ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5428ac2e8736STakashi Iwai {
5429ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5430ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5431ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
5432ac2e8736STakashi Iwai 	return 0;
5433ac2e8736STakashi Iwai }
5434ac2e8736STakashi Iwai 
5435ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5436ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5437ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5438ac2e8736STakashi Iwai {
5439ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5440ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5441ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
5442ac2e8736STakashi Iwai 	return 0;
5443ac2e8736STakashi Iwai }
5444ac2e8736STakashi Iwai 
5445ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5446ac2e8736STakashi Iwai 			     struct hda_codec *codec,
5447ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
5448ac2e8736STakashi Iwai {
5449ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5450ac2e8736STakashi Iwai 	return 0;
5451ac2e8736STakashi Iwai }
5452ac2e8736STakashi Iwai 
545338cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
545438cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
545538cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
545638cf6f1aSTakashi Iwai {
545738cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
545838cf6f1aSTakashi Iwai 	int err = 0;
545938cf6f1aSTakashi Iwai 
546038cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
5461d1f15e06STakashi Iwai 	if (spec->indep_hp && !spec->indep_hp_enabled)
546238cf6f1aSTakashi Iwai 		err = -EBUSY;
546338cf6f1aSTakashi Iwai 	else
546438cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5465e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5466e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
546738cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
546838cf6f1aSTakashi Iwai 	return err;
546938cf6f1aSTakashi Iwai }
547038cf6f1aSTakashi Iwai 
547138cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
547238cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
547338cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
547438cf6f1aSTakashi Iwai {
547538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
547638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
547738cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5478e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5479e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
548038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
548138cf6f1aSTakashi Iwai 	return 0;
548238cf6f1aSTakashi Iwai }
548338cf6f1aSTakashi Iwai 
5484e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5485e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5486e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
5487e6b85f3cSTakashi Iwai 				    unsigned int format,
5488e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5489e6b85f3cSTakashi Iwai {
5490e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5491e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5492e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
5493e6b85f3cSTakashi Iwai 	return 0;
5494e6b85f3cSTakashi Iwai }
5495e6b85f3cSTakashi Iwai 
5496e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5497e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5498e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5499e6b85f3cSTakashi Iwai {
5500e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5501e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5502e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
5503e6b85f3cSTakashi Iwai 	return 0;
5504e6b85f3cSTakashi Iwai }
5505e6b85f3cSTakashi Iwai 
5506352f7f91STakashi Iwai /*
5507352f7f91STakashi Iwai  * Digital out
5508352f7f91STakashi Iwai  */
5509352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5510352f7f91STakashi Iwai 				 struct hda_codec *codec,
5511352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
5512352f7f91STakashi Iwai {
5513352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5514352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5515352f7f91STakashi Iwai }
5516352f7f91STakashi Iwai 
5517352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5518352f7f91STakashi Iwai 				    struct hda_codec *codec,
5519352f7f91STakashi Iwai 				    unsigned int stream_tag,
5520352f7f91STakashi Iwai 				    unsigned int format,
5521352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5522352f7f91STakashi Iwai {
5523352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5524352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5525352f7f91STakashi Iwai 					     stream_tag, format, substream);
5526352f7f91STakashi Iwai }
5527352f7f91STakashi Iwai 
5528352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5529352f7f91STakashi Iwai 				    struct hda_codec *codec,
5530352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5531352f7f91STakashi Iwai {
5532352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5533352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5534352f7f91STakashi Iwai }
5535352f7f91STakashi Iwai 
5536352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5537352f7f91STakashi Iwai 				  struct hda_codec *codec,
5538352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
5539352f7f91STakashi Iwai {
5540352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5541352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5542352f7f91STakashi Iwai }
5543352f7f91STakashi Iwai 
5544352f7f91STakashi Iwai /*
5545352f7f91STakashi Iwai  * Analog capture
5546352f7f91STakashi Iwai  */
5547ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
5548ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
5549ac2e8736STakashi Iwai 
5550352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5551352f7f91STakashi Iwai 				   struct hda_codec *codec,
5552352f7f91STakashi Iwai 				   unsigned int stream_tag,
5553352f7f91STakashi Iwai 				   unsigned int format,
5554352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
5555352f7f91STakashi Iwai {
5556352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5557352f7f91STakashi Iwai 
5558352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
555997ec558aSTakashi Iwai 				   stream_tag, 0, format);
5560ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5561ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
556297ec558aSTakashi Iwai 	return 0;
556397ec558aSTakashi Iwai }
556497ec558aSTakashi Iwai 
5565352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
556697ec558aSTakashi Iwai 				   struct hda_codec *codec,
556797ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
556897ec558aSTakashi Iwai {
5569352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
557097ec558aSTakashi Iwai 
5571352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
5572352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
5573ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5574ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
557597ec558aSTakashi Iwai 	return 0;
557697ec558aSTakashi Iwai }
557797ec558aSTakashi Iwai 
5578352f7f91STakashi Iwai /*
5579352f7f91STakashi Iwai  */
5580352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
5581352f7f91STakashi Iwai 	.substreams = 1,
5582352f7f91STakashi Iwai 	.channels_min = 2,
5583352f7f91STakashi Iwai 	.channels_max = 8,
5584352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5585352f7f91STakashi Iwai 	.ops = {
5586352f7f91STakashi Iwai 		.open = playback_pcm_open,
558738cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
5588352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
5589352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
5590352f7f91STakashi Iwai 	},
5591352f7f91STakashi Iwai };
5592352f7f91STakashi Iwai 
5593352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
5594352f7f91STakashi Iwai 	.substreams = 1,
5595352f7f91STakashi Iwai 	.channels_min = 2,
5596352f7f91STakashi Iwai 	.channels_max = 2,
5597352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5598ac2e8736STakashi Iwai 	.ops = {
5599ac2e8736STakashi Iwai 		.open = capture_pcm_open,
5600ac2e8736STakashi Iwai 		.close = capture_pcm_close,
5601ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
5602ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
5603ac2e8736STakashi Iwai 	},
5604352f7f91STakashi Iwai };
5605352f7f91STakashi Iwai 
5606352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
5607352f7f91STakashi Iwai 	.substreams = 1,
5608352f7f91STakashi Iwai 	.channels_min = 2,
5609352f7f91STakashi Iwai 	.channels_max = 2,
5610352f7f91STakashi Iwai 	/* NID is set in build_pcms */
561138cf6f1aSTakashi Iwai 	.ops = {
561238cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
5613e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
5614e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
5615e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
561638cf6f1aSTakashi Iwai 	},
5617352f7f91STakashi Iwai };
5618352f7f91STakashi Iwai 
5619352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
5620352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
5621352f7f91STakashi Iwai 	.channels_min = 2,
5622352f7f91STakashi Iwai 	.channels_max = 2,
5623352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5624352f7f91STakashi Iwai 	.ops = {
5625ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5626ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5627352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5628352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5629352f7f91STakashi Iwai 	},
5630352f7f91STakashi Iwai };
5631352f7f91STakashi Iwai 
5632352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5633352f7f91STakashi Iwai 	.substreams = 1,
5634352f7f91STakashi Iwai 	.channels_min = 2,
5635352f7f91STakashi Iwai 	.channels_max = 2,
5636352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5637352f7f91STakashi Iwai 	.ops = {
5638352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5639352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5640352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5641352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5642352f7f91STakashi Iwai 	},
5643352f7f91STakashi Iwai };
5644352f7f91STakashi Iwai 
5645352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5646352f7f91STakashi Iwai 	.substreams = 1,
5647352f7f91STakashi Iwai 	.channels_min = 2,
5648352f7f91STakashi Iwai 	.channels_max = 2,
5649352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5650352f7f91STakashi Iwai };
5651352f7f91STakashi Iwai 
5652352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5653352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5654352f7f91STakashi Iwai 	.substreams = 0,
5655352f7f91STakashi Iwai 	.channels_min = 0,
5656352f7f91STakashi Iwai 	.channels_max = 0,
5657352f7f91STakashi Iwai };
5658352f7f91STakashi Iwai 
5659352f7f91STakashi Iwai /*
5660352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5661352f7f91STakashi Iwai  */
5662352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
56631da177e4SLinus Torvalds {
5664352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5665352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
56661da177e4SLinus Torvalds 
5667352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5668352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5669352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5670352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5671352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5672352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5673352f7f91STakashi Iwai 					   spec->cur_adc_format);
5674352f7f91STakashi Iwai 		return true;
5675352f7f91STakashi Iwai 	}
5676352f7f91STakashi Iwai 	return false;
5677352f7f91STakashi Iwai }
5678352f7f91STakashi Iwai 
5679352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5680352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5681352f7f91STakashi Iwai 				       struct hda_codec *codec,
5682352f7f91STakashi Iwai 				       unsigned int stream_tag,
5683352f7f91STakashi Iwai 				       unsigned int format,
5684352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5685352f7f91STakashi Iwai {
5686352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5687352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5688352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5689352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5690352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
56914f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
56921da177e4SLinus Torvalds 	return 0;
56931da177e4SLinus Torvalds }
56941da177e4SLinus Torvalds 
5695352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5696352f7f91STakashi Iwai 				       struct hda_codec *codec,
5697352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5698352f7f91STakashi Iwai {
5699352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5700352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5701352f7f91STakashi Iwai 	spec->cur_adc = 0;
57024f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
5703352f7f91STakashi Iwai 	return 0;
5704352f7f91STakashi Iwai }
5705352f7f91STakashi Iwai 
5706352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5707352f7f91STakashi Iwai 	.substreams = 1,
5708352f7f91STakashi Iwai 	.channels_min = 2,
5709352f7f91STakashi Iwai 	.channels_max = 2,
5710352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5711352f7f91STakashi Iwai 	.ops = {
5712352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5713352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5714352f7f91STakashi Iwai 	},
5715352f7f91STakashi Iwai };
5716352f7f91STakashi Iwai 
5717f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5718f873e536STakashi Iwai 				 const char *chip_name)
5719f873e536STakashi Iwai {
5720f873e536STakashi Iwai 	char *p;
5721f873e536STakashi Iwai 
5722f873e536STakashi Iwai 	if (*str)
5723f873e536STakashi Iwai 		return;
5724f873e536STakashi Iwai 	strlcpy(str, chip_name, len);
5725f873e536STakashi Iwai 
5726f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5727f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5728f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5729f873e536STakashi Iwai 			*p = 0;
5730f873e536STakashi Iwai 			break;
5731f873e536STakashi Iwai 		}
5732f873e536STakashi Iwai 	}
5733f873e536STakashi Iwai 	strlcat(str, sfx, len);
5734f873e536STakashi Iwai }
5735f873e536STakashi Iwai 
5736fb83b635STakashi Iwai /* copy PCM stream info from @default_str, and override non-NULL entries
5737fb83b635STakashi Iwai  * from @spec_str and @nid
5738fb83b635STakashi Iwai  */
5739fb83b635STakashi Iwai static void setup_pcm_stream(struct hda_pcm_stream *str,
5740fb83b635STakashi Iwai 			     const struct hda_pcm_stream *default_str,
5741fb83b635STakashi Iwai 			     const struct hda_pcm_stream *spec_str,
5742fb83b635STakashi Iwai 			     hda_nid_t nid)
5743fb83b635STakashi Iwai {
5744fb83b635STakashi Iwai 	*str = *default_str;
5745fb83b635STakashi Iwai 	if (nid)
5746fb83b635STakashi Iwai 		str->nid = nid;
5747fb83b635STakashi Iwai 	if (spec_str) {
5748fb83b635STakashi Iwai 		if (spec_str->substreams)
5749fb83b635STakashi Iwai 			str->substreams = spec_str->substreams;
5750fb83b635STakashi Iwai 		if (spec_str->channels_min)
5751fb83b635STakashi Iwai 			str->channels_min = spec_str->channels_min;
5752fb83b635STakashi Iwai 		if (spec_str->channels_max)
5753fb83b635STakashi Iwai 			str->channels_max = spec_str->channels_max;
5754fb83b635STakashi Iwai 		if (spec_str->rates)
5755fb83b635STakashi Iwai 			str->rates = spec_str->rates;
5756fb83b635STakashi Iwai 		if (spec_str->formats)
5757fb83b635STakashi Iwai 			str->formats = spec_str->formats;
5758fb83b635STakashi Iwai 		if (spec_str->maxbps)
5759fb83b635STakashi Iwai 			str->maxbps = spec_str->maxbps;
5760fb83b635STakashi Iwai 	}
5761fb83b635STakashi Iwai }
5762fb83b635STakashi Iwai 
5763dda42bd0STakashi Iwai /**
5764dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5765dda42bd0STakashi Iwai  * @codec: the HDA codec
5766dda42bd0STakashi Iwai  *
5767dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5768dda42bd0STakashi Iwai  */
5769352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5770352f7f91STakashi Iwai {
5771352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5772bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5773352f7f91STakashi Iwai 	bool have_multi_adcs;
5774352f7f91STakashi Iwai 
5775352f7f91STakashi Iwai 	if (spec->no_analog)
5776352f7f91STakashi Iwai 		goto skip_analog;
5777352f7f91STakashi Iwai 
5778f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5779f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
57807639a06cSTakashi Iwai 			     " Analog", codec->core.chip_name);
5781bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5782bbbc7e85STakashi Iwai 	if (!info)
5783bbbc7e85STakashi Iwai 		return -ENOMEM;
5784bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5785352f7f91STakashi Iwai 
5786352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5787fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5788fb83b635STakashi Iwai 				 &pcm_analog_playback,
5789fb83b635STakashi Iwai 				 spec->stream_analog_playback,
5790fb83b635STakashi Iwai 				 spec->multiout.dac_nids[0]);
5791352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5792352f7f91STakashi Iwai 			spec->multiout.max_channels;
5793352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5794352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5795352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5796352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5797352f7f91STakashi Iwai 	}
5798352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5799fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5800fb83b635STakashi Iwai 				 (spec->dyn_adc_switch ?
5801fb83b635STakashi Iwai 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5802fb83b635STakashi Iwai 				 spec->stream_analog_capture,
5803fb83b635STakashi Iwai 				 spec->adc_nids[0]);
5804352f7f91STakashi Iwai 	}
5805352f7f91STakashi Iwai 
5806352f7f91STakashi Iwai  skip_analog:
5807352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5808352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5809f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5810352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
58117639a06cSTakashi Iwai 				     " Digital", codec->core.chip_name);
5812bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5813bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5814bbbc7e85STakashi Iwai 		if (!info)
5815bbbc7e85STakashi Iwai 			return -ENOMEM;
58169ab0cb30STakashi Iwai 		codec->follower_dig_outs = spec->multiout.follower_dig_outs;
5817bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5818352f7f91STakashi Iwai 		if (spec->dig_out_type)
5819352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5820352f7f91STakashi Iwai 		else
5821352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5822fb83b635STakashi Iwai 		if (spec->multiout.dig_out_nid)
5823fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5824fb83b635STakashi Iwai 					 &pcm_digital_playback,
5825fb83b635STakashi Iwai 					 spec->stream_digital_playback,
5826fb83b635STakashi Iwai 					 spec->multiout.dig_out_nid);
5827fb83b635STakashi Iwai 		if (spec->dig_in_nid)
5828fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5829fb83b635STakashi Iwai 					 &pcm_digital_capture,
5830fb83b635STakashi Iwai 					 spec->stream_digital_capture,
5831fb83b635STakashi Iwai 					 spec->dig_in_nid);
5832352f7f91STakashi Iwai 	}
5833352f7f91STakashi Iwai 
5834352f7f91STakashi Iwai 	if (spec->no_analog)
5835352f7f91STakashi Iwai 		return 0;
5836352f7f91STakashi Iwai 
5837352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5838352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5839352f7f91STakashi Iwai 	 */
5840352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5841352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5842352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5843352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5844a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5845a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
58467639a06cSTakashi Iwai 			     " Alt Analog", codec->core.chip_name);
5847bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5848bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5849bbbc7e85STakashi Iwai 		if (!info)
5850bbbc7e85STakashi Iwai 			return -ENOMEM;
5851bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5852fb83b635STakashi Iwai 		if (spec->alt_dac_nid)
5853fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5854fb83b635STakashi Iwai 					 &pcm_analog_alt_playback,
5855fb83b635STakashi Iwai 					 spec->stream_analog_alt_playback,
5856fb83b635STakashi Iwai 					 spec->alt_dac_nid);
5857fb83b635STakashi Iwai 		else
5858fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5859fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5860352f7f91STakashi Iwai 		if (have_multi_adcs) {
5861fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5862fb83b635STakashi Iwai 					 &pcm_analog_alt_capture,
5863fb83b635STakashi Iwai 					 spec->stream_analog_alt_capture,
5864fb83b635STakashi Iwai 					 spec->adc_nids[1]);
5865352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5866352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5867352f7f91STakashi Iwai 		} else {
5868fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5869fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5870352f7f91STakashi Iwai 		}
58711da177e4SLinus Torvalds 	}
58721da177e4SLinus Torvalds 
58731da177e4SLinus Torvalds 	return 0;
58741da177e4SLinus Torvalds }
58752698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5876352f7f91STakashi Iwai 
5877352f7f91STakashi Iwai 
5878352f7f91STakashi Iwai /*
5879352f7f91STakashi Iwai  * Standard auto-parser initializations
5880352f7f91STakashi Iwai  */
5881352f7f91STakashi Iwai 
5882d4156930STakashi Iwai /* configure the given path as a proper output */
58832c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5884352f7f91STakashi Iwai {
5885352f7f91STakashi Iwai 	struct nid_path *path;
5886d4156930STakashi Iwai 	hda_nid_t pin;
5887352f7f91STakashi Iwai 
5888196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5889d4156930STakashi Iwai 	if (!path || !path->depth)
5890352f7f91STakashi Iwai 		return;
5891d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
58922c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
589365033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
589465033cc8STakashi Iwai 			      aamix_default(codec->spec));
5895e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5896352f7f91STakashi Iwai }
5897352f7f91STakashi Iwai 
5898352f7f91STakashi Iwai /* initialize primary output paths */
5899352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5900352f7f91STakashi Iwai {
5901352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5902352f7f91STakashi Iwai 	int i;
5903352f7f91STakashi Iwai 
5904d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
59052c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5906352f7f91STakashi Iwai }
5907352f7f91STakashi Iwai 
5908db23fd19STakashi Iwai 
59092c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5910352f7f91STakashi Iwai {
5911352f7f91STakashi Iwai 	int i;
5912352f7f91STakashi Iwai 
5913d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
59142c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5915352f7f91STakashi Iwai }
5916db23fd19STakashi Iwai 
5917db23fd19STakashi Iwai /* initialize hp and speaker paths */
5918db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5919db23fd19STakashi Iwai {
5920db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5921db23fd19STakashi Iwai 
5922db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
59232c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5924db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5925db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
59262c12c30dSTakashi Iwai 				 spec->speaker_paths);
5927352f7f91STakashi Iwai }
5928352f7f91STakashi Iwai 
5929352f7f91STakashi Iwai /* initialize multi-io paths */
5930352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5931352f7f91STakashi Iwai {
5932352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5933352f7f91STakashi Iwai 	int i;
5934352f7f91STakashi Iwai 
5935352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5936352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5937352f7f91STakashi Iwai 		struct nid_path *path;
5938196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5939352f7f91STakashi Iwai 		if (!path)
5940352f7f91STakashi Iwai 			continue;
5941352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5942352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
59432c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
594465033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
594565033cc8STakashi Iwai 				      aamix_default(spec));
5946352f7f91STakashi Iwai 	}
5947352f7f91STakashi Iwai }
5948352f7f91STakashi Iwai 
59494f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
59504f7f67fbSTakashi Iwai {
59514f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
59524f7f67fbSTakashi Iwai 
59534f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
59544f7f67fbSTakashi Iwai 		return;
5955e7fdd527STakashi Iwai 	if (!has_aamix_out_paths(spec))
5956e7fdd527STakashi Iwai 		return;
59574f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
59584f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
59594f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
59604f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
59614f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
59624f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
59634f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
59644f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
59654f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
59664f7f67fbSTakashi Iwai }
59674f7f67fbSTakashi Iwai 
5968352f7f91STakashi Iwai /* set up input pins and loopback paths */
5969352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5970352f7f91STakashi Iwai {
5971352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5972352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5973352f7f91STakashi Iwai 	int i;
5974352f7f91STakashi Iwai 
5975352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5976352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5977352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
59782c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5979352f7f91STakashi Iwai 
5980352f7f91STakashi Iwai 		/* init loopback inputs */
5981352f7f91STakashi Iwai 		if (spec->mixer_nid) {
59823e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
59833e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5984352f7f91STakashi Iwai 		}
5985352f7f91STakashi Iwai 	}
5986352f7f91STakashi Iwai }
5987352f7f91STakashi Iwai 
5988352f7f91STakashi Iwai /* initialize ADC paths */
5989352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5990352f7f91STakashi Iwai {
5991352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5992352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5993352f7f91STakashi Iwai 	struct nid_path *path;
5994352f7f91STakashi Iwai 	int i, c, nums;
5995352f7f91STakashi Iwai 
5996352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5997352f7f91STakashi Iwai 		nums = 1;
5998352f7f91STakashi Iwai 	else
5999352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
6000352f7f91STakashi Iwai 
6001352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
6002352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
6003c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
6004352f7f91STakashi Iwai 			if (path) {
6005352f7f91STakashi Iwai 				bool active = path->active;
6006352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
6007352f7f91STakashi Iwai 					active = true;
6008352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
6009352f7f91STakashi Iwai 			}
6010352f7f91STakashi Iwai 		}
6011967303daSTakashi Iwai 		if (spec->hp_mic)
6012967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
6013352f7f91STakashi Iwai 	}
6014352f7f91STakashi Iwai 
6015352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
60167fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
6017352f7f91STakashi Iwai }
6018352f7f91STakashi Iwai 
6019352f7f91STakashi Iwai /* set right pin controls for digital I/O */
6020352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
6021352f7f91STakashi Iwai {
6022352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6023352f7f91STakashi Iwai 	int i;
6024352f7f91STakashi Iwai 	hda_nid_t pin;
6025352f7f91STakashi Iwai 
6026d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
60272c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
6028352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
60292430d7b7STakashi Iwai 	if (pin) {
60302c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
60313e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
60322430d7b7STakashi Iwai 	}
6033352f7f91STakashi Iwai }
6034352f7f91STakashi Iwai 
6035973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
6036973e4972STakashi Iwai  * invalid unsol tags by some reason
6037973e4972STakashi Iwai  */
6038973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
6039973e4972STakashi Iwai {
6040a9c2dfc8STakashi Iwai 	const struct hda_pincfg *pin;
6041973e4972STakashi Iwai 	int i;
6042973e4972STakashi Iwai 
6043a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->init_pins, i, pin) {
6044973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
6045973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
6046973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
6047401caff7STakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
6048973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
6049973e4972STakashi Iwai 	}
6050973e4972STakashi Iwai }
6051973e4972STakashi Iwai 
6052dda42bd0STakashi Iwai /**
6053dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
6054dda42bd0STakashi Iwai  * @codec: the HDA codec
6055dda42bd0STakashi Iwai  *
6056dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
60575187ac16STakashi Iwai  */
6058352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
6059352f7f91STakashi Iwai {
6060352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6061352f7f91STakashi Iwai 
6062352f7f91STakashi Iwai 	if (spec->init_hook)
6063352f7f91STakashi Iwai 		spec->init_hook(codec);
6064352f7f91STakashi Iwai 
606589781d08STakashi Iwai 	if (!spec->skip_verbs)
6066352f7f91STakashi Iwai 		snd_hda_apply_verbs(codec);
6067352f7f91STakashi Iwai 
6068352f7f91STakashi Iwai 	init_multi_out(codec);
6069352f7f91STakashi Iwai 	init_extra_out(codec);
6070352f7f91STakashi Iwai 	init_multi_io(codec);
60714f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
6072352f7f91STakashi Iwai 	init_analog_input(codec);
6073352f7f91STakashi Iwai 	init_input_src(codec);
6074352f7f91STakashi Iwai 	init_digital(codec);
6075352f7f91STakashi Iwai 
6076973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
6077973e4972STakashi Iwai 
6078e6feb5d0STakashi Iwai 	sync_all_pin_power_ctls(codec);
6079e6feb5d0STakashi Iwai 
6080352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
6081a5cc2509STakashi Iwai 	update_automute_all(codec);
6082352f7f91STakashi Iwai 
60831a462be5STakashi Iwai 	snd_hda_regmap_sync(codec);
60843bbcd274STakashi Iwai 
6085352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
6086352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
6087352f7f91STakashi Iwai 
6088352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
6089352f7f91STakashi Iwai 	return 0;
6090352f7f91STakashi Iwai }
60912698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
6092fce52a3bSTakashi Iwai 
6093dda42bd0STakashi Iwai /**
6094dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
6095dda42bd0STakashi Iwai  * @codec: the HDA codec
6096dda42bd0STakashi Iwai  *
6097dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
60985187ac16STakashi Iwai  */
6099fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
6100fce52a3bSTakashi Iwai {
61018a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
6102fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
6103fce52a3bSTakashi Iwai 	kfree(codec->spec);
6104fce52a3bSTakashi Iwai 	codec->spec = NULL;
6105fce52a3bSTakashi Iwai }
61062698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
6107fce52a3bSTakashi Iwai 
6108871b9066SHui Wang /**
6109871b9066SHui Wang  * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
6110871b9066SHui Wang  * @codec: the HDA codec
6111871b9066SHui Wang  *
6112871b9066SHui Wang  * This can be put as patch_ops reboot_notify function.
6113871b9066SHui Wang  */
6114871b9066SHui Wang void snd_hda_gen_reboot_notify(struct hda_codec *codec)
6115871b9066SHui Wang {
6116871b9066SHui Wang 	/* Make the codec enter D3 to avoid spurious noises from the internal
6117871b9066SHui Wang 	 * speaker during (and after) reboot
6118871b9066SHui Wang 	 */
6119871b9066SHui Wang 	snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
6120871b9066SHui Wang 	snd_hda_codec_write(codec, codec->core.afg, 0,
6121871b9066SHui Wang 			    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
6122871b9066SHui Wang 	msleep(10);
6123871b9066SHui Wang }
6124871b9066SHui Wang EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
6125871b9066SHui Wang 
6126fce52a3bSTakashi Iwai #ifdef CONFIG_PM
6127dda42bd0STakashi Iwai /**
6128dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
6129dda42bd0STakashi Iwai  * @codec: the HDA codec
6130dda42bd0STakashi Iwai  * @nid: NID to inspect
6131dda42bd0STakashi Iwai  *
6132dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
61335187ac16STakashi Iwai  */
6134fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
6135fce52a3bSTakashi Iwai {
6136fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6137fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
6138fce52a3bSTakashi Iwai }
61392698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
6140fce52a3bSTakashi Iwai #endif
6141352f7f91STakashi Iwai 
6142352f7f91STakashi Iwai 
6143352f7f91STakashi Iwai /*
6144352f7f91STakashi Iwai  * the generic codec support
6145352f7f91STakashi Iwai  */
61461da177e4SLinus Torvalds 
6147352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
6148352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
6149352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
6150352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
6151fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
6152352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
6153871b9066SHui Wang 	.reboot_notify = snd_hda_gen_reboot_notify,
615483012a7cSTakashi Iwai #ifdef CONFIG_PM
6155fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
6156cb53c626STakashi Iwai #endif
61571da177e4SLinus Torvalds };
61581da177e4SLinus Torvalds 
6159d8a766a1STakashi Iwai /*
6160dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
6161dda42bd0STakashi Iwai  * @codec: the HDA codec
6162dda42bd0STakashi Iwai  */
6163d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
61641da177e4SLinus Torvalds {
6165352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
61661da177e4SLinus Torvalds 	int err;
61671da177e4SLinus Torvalds 
6168e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6169352f7f91STakashi Iwai 	if (!spec)
61701da177e4SLinus Torvalds 		return -ENOMEM;
6171352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
61721da177e4SLinus Torvalds 	codec->spec = spec;
61731da177e4SLinus Torvalds 
61749eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
61759eb413e5STakashi Iwai 	if (err < 0)
6176cfef67f0SWenwen Wang 		goto error;
61779eb413e5STakashi Iwai 
61789eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
6179352f7f91STakashi Iwai 	if (err < 0)
61801da177e4SLinus Torvalds 		goto error;
61811da177e4SLinus Torvalds 
61821da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
61831da177e4SLinus Torvalds 	return 0;
61841da177e4SLinus Torvalds 
61851da177e4SLinus Torvalds error:
6186fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
61871da177e4SLinus Torvalds 	return err;
61881da177e4SLinus Torvalds }
6189d8a766a1STakashi Iwai 
6190b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_generic[] = {
6191b9a94a9cSTakashi Iwai 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
6192d8a766a1STakashi Iwai 	{} /* terminator */
6193d8a766a1STakashi Iwai };
6194b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
6195d8a766a1STakashi Iwai 
6196d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
6197b9a94a9cSTakashi Iwai 	.id = snd_hda_id_generic,
6198d8a766a1STakashi Iwai };
6199d8a766a1STakashi Iwai 
6200d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
6201b21bdd0dSTakashi Iwai 
6202b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
6203b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
6204