xref: /linux/sound/pci/hda/hda_generic.c (revision be602cde657ee43d23adbf309be6d700d0106dc9)
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);
94549f8ffcSTakashi Iwai #ifdef CONFIG_SND_HDA_GENERIC_LEDS
95549f8ffcSTakashi Iwai 	if (spec->led_cdevs[LED_AUDIO_MUTE])
96549f8ffcSTakashi Iwai 		led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]);
97549f8ffcSTakashi Iwai 	if (spec->led_cdevs[LED_AUDIO_MICMUTE])
98549f8ffcSTakashi Iwai 		led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]);
99549f8ffcSTakashi Iwai #endif
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds 
1021da177e4SLinus Torvalds /*
1031c70a583STakashi Iwai  * store user hints
1041c70a583STakashi Iwai  */
1051c70a583STakashi Iwai static void parse_user_hints(struct hda_codec *codec)
1061c70a583STakashi Iwai {
1071c70a583STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1081c70a583STakashi Iwai 	int val;
1091c70a583STakashi Iwai 
1101c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "jack_detect");
1111c70a583STakashi Iwai 	if (val >= 0)
1121c70a583STakashi Iwai 		codec->no_jack_detect = !val;
1131c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
1141c70a583STakashi Iwai 	if (val >= 0)
1151c70a583STakashi Iwai 		codec->inv_jack_detect = !!val;
1161c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
1171c70a583STakashi Iwai 	if (val >= 0)
1181c70a583STakashi Iwai 		codec->no_trigger_sense = !val;
1191c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
1201c70a583STakashi Iwai 	if (val >= 0)
1211c70a583STakashi Iwai 		codec->inv_eapd = !!val;
1221c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
1231c70a583STakashi Iwai 	if (val >= 0)
1241c70a583STakashi Iwai 		codec->pcm_format_first = !!val;
1251c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
1261c70a583STakashi Iwai 	if (val >= 0)
1271c70a583STakashi Iwai 		codec->no_sticky_stream = !val;
1281c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
1291c70a583STakashi Iwai 	if (val >= 0)
1301c70a583STakashi Iwai 		codec->spdif_status_reset = !!val;
1311c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
1321c70a583STakashi Iwai 	if (val >= 0)
1331c70a583STakashi Iwai 		codec->pin_amp_workaround = !!val;
1341c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
1351c70a583STakashi Iwai 	if (val >= 0)
1361c70a583STakashi Iwai 		codec->single_adc_amp = !!val;
137967b1307STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_save_node");
138e6feb5d0STakashi Iwai 	if (val >= 0)
139967b1307STakashi Iwai 		codec->power_save_node = !!val;
1401c70a583STakashi Iwai 
141f72706beSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute");
142f72706beSTakashi Iwai 	if (val >= 0)
143f72706beSTakashi Iwai 		spec->suppress_auto_mute = !val;
1441c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mic");
1451c70a583STakashi Iwai 	if (val >= 0)
1461c70a583STakashi Iwai 		spec->suppress_auto_mic = !val;
1471c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
1481c70a583STakashi Iwai 	if (val >= 0)
1491c70a583STakashi Iwai 		spec->line_in_auto_switch = !!val;
1507eebffd3STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
1517eebffd3STakashi Iwai 	if (val >= 0)
1527eebffd3STakashi Iwai 		spec->auto_mute_via_amp = !!val;
1531c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
1541c70a583STakashi Iwai 	if (val >= 0)
1551c70a583STakashi Iwai 		spec->need_dac_fix = !!val;
1561c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "primary_hp");
1571c70a583STakashi Iwai 	if (val >= 0)
1581c70a583STakashi Iwai 		spec->no_primary_hp = !val;
159da96fb5bSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_io");
160da96fb5bSTakashi Iwai 	if (val >= 0)
161da96fb5bSTakashi Iwai 		spec->no_multi_io = !val;
1621c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
1631c70a583STakashi Iwai 	if (val >= 0)
1641c70a583STakashi Iwai 		spec->multi_cap_vol = !!val;
1651c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
1661c70a583STakashi Iwai 	if (val >= 0)
1671c70a583STakashi Iwai 		spec->inv_dmic_split = !!val;
1681c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "indep_hp");
1691c70a583STakashi Iwai 	if (val >= 0)
1701c70a583STakashi Iwai 		spec->indep_hp = !!val;
1711c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
1721c70a583STakashi Iwai 	if (val >= 0)
1731c70a583STakashi Iwai 		spec->add_stereo_mix_input = !!val;
174f811c3cfSTakashi Iwai 	/* the following two are just for compatibility */
1751c70a583STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
1761c70a583STakashi Iwai 	if (val >= 0)
177f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
17829476558STakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
17929476558STakashi Iwai 	if (val >= 0)
180f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
181f811c3cfSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
182f811c3cfSTakashi Iwai 	if (val >= 0)
183f811c3cfSTakashi Iwai 		spec->add_jack_modes = !!val;
18455196fffSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
18555196fffSTakashi Iwai 	if (val >= 0)
18655196fffSTakashi Iwai 		spec->power_down_unused = !!val;
187967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
188967303daSTakashi Iwai 	if (val >= 0)
189967303daSTakashi Iwai 		spec->hp_mic = !!val;
190967303daSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
191967303daSTakashi Iwai 	if (val >= 0)
192967303daSTakashi Iwai 		spec->suppress_hp_mic_detect = !val;
1937480316cSTakashi Iwai 	val = snd_hda_get_bool_hint(codec, "vmaster");
1947480316cSTakashi Iwai 	if (val >= 0)
1957480316cSTakashi Iwai 		spec->suppress_vmaster = !val;
1961c70a583STakashi Iwai 
1971c70a583STakashi Iwai 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
1981c70a583STakashi Iwai 		spec->mixer_nid = val;
1991c70a583STakashi Iwai }
2001c70a583STakashi Iwai 
2011c70a583STakashi Iwai /*
2022c12c30dSTakashi Iwai  * pin control value accesses
2032c12c30dSTakashi Iwai  */
2042c12c30dSTakashi Iwai 
2052c12c30dSTakashi Iwai #define update_pin_ctl(codec, pin, val) \
206401caff7STakashi Iwai 	snd_hda_codec_write_cache(codec, pin, 0, \
2072c12c30dSTakashi Iwai 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
2082c12c30dSTakashi Iwai 
2092c12c30dSTakashi Iwai /* restore the pinctl based on the cached value */
2102c12c30dSTakashi Iwai static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
2112c12c30dSTakashi Iwai {
2122c12c30dSTakashi Iwai 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
2132c12c30dSTakashi Iwai }
2142c12c30dSTakashi Iwai 
2152c12c30dSTakashi Iwai /* set the pinctl target value and write it if requested */
2162c12c30dSTakashi Iwai static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
2172c12c30dSTakashi Iwai 			   unsigned int val, bool do_write)
2182c12c30dSTakashi Iwai {
2192c12c30dSTakashi Iwai 	if (!pin)
2202c12c30dSTakashi Iwai 		return;
2212c12c30dSTakashi Iwai 	val = snd_hda_correct_pin_ctl(codec, pin, val);
2222c12c30dSTakashi Iwai 	snd_hda_codec_set_pin_target(codec, pin, val);
2232c12c30dSTakashi Iwai 	if (do_write)
2242c12c30dSTakashi Iwai 		update_pin_ctl(codec, pin, val);
2252c12c30dSTakashi Iwai }
2262c12c30dSTakashi Iwai 
2272c12c30dSTakashi Iwai /* set pinctl target values for all given pins */
2282c12c30dSTakashi Iwai static void set_pin_targets(struct hda_codec *codec, int num_pins,
2292c12c30dSTakashi Iwai 			    hda_nid_t *pins, unsigned int val)
2302c12c30dSTakashi Iwai {
2312c12c30dSTakashi Iwai 	int i;
2322c12c30dSTakashi Iwai 	for (i = 0; i < num_pins; i++)
2332c12c30dSTakashi Iwai 		set_pin_target(codec, pins[i], val, false);
2342c12c30dSTakashi Iwai }
2352c12c30dSTakashi Iwai 
2362c12c30dSTakashi Iwai /*
237352f7f91STakashi Iwai  * parsing paths
2381da177e4SLinus Torvalds  */
2391da177e4SLinus Torvalds 
2403ca529d3STakashi Iwai /* return the position of NID in the list, or -1 if not found */
2413ca529d3STakashi Iwai static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
2423ca529d3STakashi Iwai {
2433ca529d3STakashi Iwai 	int i;
2443ca529d3STakashi Iwai 	for (i = 0; i < nums; i++)
2453ca529d3STakashi Iwai 		if (list[i] == nid)
2463ca529d3STakashi Iwai 			return i;
2473ca529d3STakashi Iwai 	return -1;
2483ca529d3STakashi Iwai }
2493ca529d3STakashi Iwai 
2503ca529d3STakashi Iwai /* return true if the given NID is contained in the path */
2513ca529d3STakashi Iwai static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
2523ca529d3STakashi Iwai {
2533ca529d3STakashi Iwai 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
2543ca529d3STakashi Iwai }
2553ca529d3STakashi Iwai 
256f5172a7eSTakashi Iwai static struct nid_path *get_nid_path(struct hda_codec *codec,
257f5172a7eSTakashi Iwai 				     hda_nid_t from_nid, hda_nid_t to_nid,
2583ca529d3STakashi Iwai 				     int anchor_nid)
2591da177e4SLinus Torvalds {
260352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
261a9c2dfc8STakashi Iwai 	struct nid_path *path;
262352f7f91STakashi Iwai 	int i;
2631da177e4SLinus Torvalds 
264a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
265352f7f91STakashi Iwai 		if (path->depth <= 0)
266352f7f91STakashi Iwai 			continue;
267352f7f91STakashi Iwai 		if ((!from_nid || path->path[0] == from_nid) &&
268f5172a7eSTakashi Iwai 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
2693ca529d3STakashi Iwai 			if (!anchor_nid ||
2703ca529d3STakashi Iwai 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
2713ca529d3STakashi Iwai 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
272352f7f91STakashi Iwai 				return path;
2731da177e4SLinus Torvalds 		}
274f5172a7eSTakashi Iwai 	}
2751da177e4SLinus Torvalds 	return NULL;
2761da177e4SLinus Torvalds }
277f5172a7eSTakashi Iwai 
278dda42bd0STakashi Iwai /**
279dda42bd0STakashi Iwai  * snd_hda_get_path_idx - get the index number corresponding to the path
280dda42bd0STakashi Iwai  * instance
281dda42bd0STakashi Iwai  * @codec: the HDA codec
282dda42bd0STakashi Iwai  * @path: nid_path object
283dda42bd0STakashi Iwai  *
284dda42bd0STakashi Iwai  * The returned index starts from 1, i.e. the actual array index with offset 1,
285dda42bd0STakashi Iwai  * and zero is handled as an invalid path
286196c1766STakashi Iwai  */
287196c1766STakashi Iwai int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
288196c1766STakashi Iwai {
289196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
290196c1766STakashi Iwai 	struct nid_path *array = spec->paths.list;
291196c1766STakashi Iwai 	ssize_t idx;
292196c1766STakashi Iwai 
293196c1766STakashi Iwai 	if (!spec->paths.used)
294196c1766STakashi Iwai 		return 0;
295196c1766STakashi Iwai 	idx = path - array;
296196c1766STakashi Iwai 	if (idx < 0 || idx >= spec->paths.used)
297196c1766STakashi Iwai 		return 0;
298196c1766STakashi Iwai 	return idx + 1;
299196c1766STakashi Iwai }
3002698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
301196c1766STakashi Iwai 
302dda42bd0STakashi Iwai /**
303dda42bd0STakashi Iwai  * snd_hda_get_path_from_idx - get the path instance corresponding to the
304dda42bd0STakashi Iwai  * given index number
305dda42bd0STakashi Iwai  * @codec: the HDA codec
306dda42bd0STakashi Iwai  * @idx: the path index
307dda42bd0STakashi Iwai  */
308196c1766STakashi Iwai struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
309196c1766STakashi Iwai {
310196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
311196c1766STakashi Iwai 
312196c1766STakashi Iwai 	if (idx <= 0 || idx > spec->paths.used)
313196c1766STakashi Iwai 		return NULL;
314196c1766STakashi Iwai 	return snd_array_elem(&spec->paths, idx - 1);
315196c1766STakashi Iwai }
3162698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
317196c1766STakashi Iwai 
318352f7f91STakashi Iwai /* check whether the given DAC is already found in any existing paths */
319352f7f91STakashi Iwai static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
3201da177e4SLinus Torvalds {
321352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
322a9c2dfc8STakashi Iwai 	const struct nid_path *path;
323352f7f91STakashi Iwai 	int i;
324352f7f91STakashi Iwai 
325a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
326352f7f91STakashi Iwai 		if (path->path[0] == nid)
327352f7f91STakashi Iwai 			return true;
328352f7f91STakashi Iwai 	}
329352f7f91STakashi Iwai 	return false;
3301da177e4SLinus Torvalds }
3311da177e4SLinus Torvalds 
332352f7f91STakashi Iwai /* check whether the given two widgets can be connected */
333352f7f91STakashi Iwai static bool is_reachable_path(struct hda_codec *codec,
334352f7f91STakashi Iwai 			      hda_nid_t from_nid, hda_nid_t to_nid)
3351da177e4SLinus Torvalds {
336352f7f91STakashi Iwai 	if (!from_nid || !to_nid)
337352f7f91STakashi Iwai 		return false;
338352f7f91STakashi Iwai 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
3391da177e4SLinus Torvalds }
3401da177e4SLinus Torvalds 
341352f7f91STakashi Iwai /* nid, dir and idx */
342352f7f91STakashi Iwai #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
343352f7f91STakashi Iwai 
344352f7f91STakashi Iwai /* check whether the given ctl is already assigned in any path elements */
345352f7f91STakashi Iwai static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
3461da177e4SLinus Torvalds {
347352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
348a9c2dfc8STakashi Iwai 	const struct nid_path *path;
349352f7f91STakashi Iwai 	int i;
350352f7f91STakashi Iwai 
351352f7f91STakashi Iwai 	val &= AMP_VAL_COMPARE_MASK;
352a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, i, path) {
353352f7f91STakashi Iwai 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
354352f7f91STakashi Iwai 			return true;
355352f7f91STakashi Iwai 	}
356352f7f91STakashi Iwai 	return false;
3571da177e4SLinus Torvalds }
3581da177e4SLinus Torvalds 
359352f7f91STakashi Iwai /* check whether a control with the given (nid, dir, idx) was assigned */
360352f7f91STakashi Iwai static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
3618999bf0aSTakashi Iwai 			      int dir, int idx, int type)
362cb53c626STakashi Iwai {
363352f7f91STakashi Iwai 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
3648999bf0aSTakashi Iwai 	return is_ctl_used(codec, val, type);
365cb53c626STakashi Iwai }
366352f7f91STakashi Iwai 
3674e76a883STakashi Iwai static void print_nid_path(struct hda_codec *codec,
3684e76a883STakashi Iwai 			   const char *pfx, struct nid_path *path)
3690c8c0f56STakashi Iwai {
3700c8c0f56STakashi Iwai 	char buf[40];
371d82353e5SJoe Perches 	char *pos = buf;
3720c8c0f56STakashi Iwai 	int i;
3730c8c0f56STakashi Iwai 
374d82353e5SJoe Perches 	*pos = 0;
375d82353e5SJoe Perches 	for (i = 0; i < path->depth; i++)
376d82353e5SJoe Perches 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
377d82353e5SJoe Perches 				 pos != buf ? ":" : "",
378d82353e5SJoe Perches 				 path->path[i]);
3790c8c0f56STakashi Iwai 
380d82353e5SJoe Perches 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
3810c8c0f56STakashi Iwai }
3820c8c0f56STakashi Iwai 
383352f7f91STakashi Iwai /* called recursively */
384352f7f91STakashi Iwai static bool __parse_nid_path(struct hda_codec *codec,
385352f7f91STakashi Iwai 			     hda_nid_t from_nid, hda_nid_t to_nid,
3863ca529d3STakashi Iwai 			     int anchor_nid, struct nid_path *path,
3873ca529d3STakashi Iwai 			     int depth)
388352f7f91STakashi Iwai {
389ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
390352f7f91STakashi Iwai 	int i, nums;
391352f7f91STakashi Iwai 
3923ca529d3STakashi Iwai 	if (to_nid == anchor_nid)
3933ca529d3STakashi Iwai 		anchor_nid = 0; /* anchor passed */
3943ca529d3STakashi Iwai 	else if (to_nid == (hda_nid_t)(-anchor_nid))
3953ca529d3STakashi Iwai 		return false; /* hit the exclusive nid */
396352f7f91STakashi Iwai 
397ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
398352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
399352f7f91STakashi Iwai 		if (conn[i] != from_nid) {
400352f7f91STakashi Iwai 			/* special case: when from_nid is 0,
401352f7f91STakashi Iwai 			 * try to find an empty DAC
402352f7f91STakashi Iwai 			 */
403352f7f91STakashi Iwai 			if (from_nid ||
404352f7f91STakashi Iwai 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
405352f7f91STakashi Iwai 			    is_dac_already_used(codec, conn[i]))
406352f7f91STakashi Iwai 				continue;
407352f7f91STakashi Iwai 		}
4083ca529d3STakashi Iwai 		/* anchor is not requested or already passed? */
4093ca529d3STakashi Iwai 		if (anchor_nid <= 0)
410352f7f91STakashi Iwai 			goto found;
411352f7f91STakashi Iwai 	}
412352f7f91STakashi Iwai 	if (depth >= MAX_NID_PATH_DEPTH)
413352f7f91STakashi Iwai 		return false;
414352f7f91STakashi Iwai 	for (i = 0; i < nums; i++) {
415352f7f91STakashi Iwai 		unsigned int type;
416352f7f91STakashi Iwai 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
417352f7f91STakashi Iwai 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
418352f7f91STakashi Iwai 		    type == AC_WID_PIN)
419352f7f91STakashi Iwai 			continue;
420352f7f91STakashi Iwai 		if (__parse_nid_path(codec, from_nid, conn[i],
4213ca529d3STakashi Iwai 				     anchor_nid, path, depth + 1))
422352f7f91STakashi Iwai 			goto found;
423352f7f91STakashi Iwai 	}
424352f7f91STakashi Iwai 	return false;
425352f7f91STakashi Iwai 
426352f7f91STakashi Iwai  found:
427352f7f91STakashi Iwai 	path->path[path->depth] = conn[i];
428352f7f91STakashi Iwai 	path->idx[path->depth + 1] = i;
429352f7f91STakashi Iwai 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
430352f7f91STakashi Iwai 		path->multi[path->depth + 1] = 1;
431352f7f91STakashi Iwai 	path->depth++;
432352f7f91STakashi Iwai 	return true;
433352f7f91STakashi Iwai }
434352f7f91STakashi Iwai 
435c4a58c30STakashi Iwai /*
436dda42bd0STakashi Iwai  * snd_hda_parse_nid_path - parse the widget path from the given nid to
437dda42bd0STakashi Iwai  * the target nid
438dda42bd0STakashi Iwai  * @codec: the HDA codec
439dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
440dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
441dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication
442dda42bd0STakashi Iwai  * @path: the path object to store the result
443dda42bd0STakashi Iwai  *
444dda42bd0STakashi Iwai  * Returns true if a matching path is found.
445dda42bd0STakashi Iwai  *
446dda42bd0STakashi Iwai  * The parsing behavior depends on parameters:
447352f7f91STakashi Iwai  * when @from_nid is 0, try to find an empty DAC;
4483ca529d3STakashi Iwai  * when @anchor_nid is set to a positive value, only paths through the widget
4493ca529d3STakashi Iwai  * with the given value are evaluated.
4503ca529d3STakashi Iwai  * when @anchor_nid is set to a negative value, paths through the widget
4513ca529d3STakashi Iwai  * with the negative of given value are excluded, only other paths are chosen.
4523ca529d3STakashi Iwai  * when @anchor_nid is zero, no special handling about path selection.
453352f7f91STakashi Iwai  */
454c4a58c30STakashi Iwai static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
4553ca529d3STakashi Iwai 			    hda_nid_t to_nid, int anchor_nid,
456352f7f91STakashi Iwai 			    struct nid_path *path)
457352f7f91STakashi Iwai {
4583ca529d3STakashi Iwai 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
459352f7f91STakashi Iwai 		path->path[path->depth] = to_nid;
460352f7f91STakashi Iwai 		path->depth++;
461352f7f91STakashi Iwai 		return true;
462352f7f91STakashi Iwai 	}
463352f7f91STakashi Iwai 	return false;
464352f7f91STakashi Iwai }
465352f7f91STakashi Iwai 
466dda42bd0STakashi Iwai /**
467dda42bd0STakashi Iwai  * snd_hda_add_new_path - parse the path between the given NIDs and
468dda42bd0STakashi Iwai  * add to the path list
469dda42bd0STakashi Iwai  * @codec: the HDA codec
470dda42bd0STakashi Iwai  * @from_nid: the NID where the path start from
471dda42bd0STakashi Iwai  * @to_nid: the NID where the path ends at
472dda42bd0STakashi Iwai  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
473dda42bd0STakashi Iwai  *
474dda42bd0STakashi Iwai  * If no valid path is found, returns NULL.
475352f7f91STakashi Iwai  */
476352f7f91STakashi Iwai struct nid_path *
477352f7f91STakashi Iwai snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
4783ca529d3STakashi Iwai 		     hda_nid_t to_nid, int anchor_nid)
479352f7f91STakashi Iwai {
480352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
481352f7f91STakashi Iwai 	struct nid_path *path;
482352f7f91STakashi Iwai 
483352f7f91STakashi Iwai 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
484352f7f91STakashi Iwai 		return NULL;
485352f7f91STakashi Iwai 
486f5172a7eSTakashi Iwai 	/* check whether the path has been already added */
4873ca529d3STakashi Iwai 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
488f5172a7eSTakashi Iwai 	if (path)
489f5172a7eSTakashi Iwai 		return path;
490f5172a7eSTakashi Iwai 
491352f7f91STakashi Iwai 	path = snd_array_new(&spec->paths);
492352f7f91STakashi Iwai 	if (!path)
493352f7f91STakashi Iwai 		return NULL;
494352f7f91STakashi Iwai 	memset(path, 0, sizeof(*path));
4953ca529d3STakashi Iwai 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
496352f7f91STakashi Iwai 		return path;
497352f7f91STakashi Iwai 	/* push back */
498352f7f91STakashi Iwai 	spec->paths.used--;
499352f7f91STakashi Iwai 	return NULL;
500352f7f91STakashi Iwai }
5012698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
502352f7f91STakashi Iwai 
503980428ceSTakashi Iwai /* clear the given path as invalid so that it won't be picked up later */
504980428ceSTakashi Iwai static void invalidate_nid_path(struct hda_codec *codec, int idx)
505980428ceSTakashi Iwai {
506980428ceSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
507980428ceSTakashi Iwai 	if (!path)
508980428ceSTakashi Iwai 		return;
509980428ceSTakashi Iwai 	memset(path, 0, sizeof(*path));
510980428ceSTakashi Iwai }
511980428ceSTakashi Iwai 
5123690739bSTakashi Iwai /* return a DAC if paired to the given pin by codec driver */
5133690739bSTakashi Iwai static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
5143690739bSTakashi Iwai {
5153690739bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5163690739bSTakashi Iwai 	const hda_nid_t *list = spec->preferred_dacs;
5173690739bSTakashi Iwai 
5183690739bSTakashi Iwai 	if (!list)
5193690739bSTakashi Iwai 		return 0;
5203690739bSTakashi Iwai 	for (; *list; list += 2)
5213690739bSTakashi Iwai 		if (*list == pin)
5223690739bSTakashi Iwai 			return list[1];
5233690739bSTakashi Iwai 	return 0;
5243690739bSTakashi Iwai }
5253690739bSTakashi Iwai 
526352f7f91STakashi Iwai /* look for an empty DAC slot */
527352f7f91STakashi Iwai static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
528352f7f91STakashi Iwai 			      bool is_digital)
529352f7f91STakashi Iwai {
530352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
531352f7f91STakashi Iwai 	bool cap_digital;
532352f7f91STakashi Iwai 	int i;
533352f7f91STakashi Iwai 
534352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
535352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
536352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
537352f7f91STakashi Iwai 			continue;
538352f7f91STakashi Iwai 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
539352f7f91STakashi Iwai 		if (is_digital != cap_digital)
540352f7f91STakashi Iwai 			continue;
541352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin))
542352f7f91STakashi Iwai 			return nid;
543352f7f91STakashi Iwai 	}
544352f7f91STakashi Iwai 	return 0;
545352f7f91STakashi Iwai }
546352f7f91STakashi Iwai 
547352f7f91STakashi Iwai /* replace the channels in the composed amp value with the given number */
548352f7f91STakashi Iwai static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
549352f7f91STakashi Iwai {
550352f7f91STakashi Iwai 	val &= ~(0x3U << 16);
551352f7f91STakashi Iwai 	val |= chs << 16;
552352f7f91STakashi Iwai 	return val;
553352f7f91STakashi Iwai }
554352f7f91STakashi Iwai 
55599a5592dSDavid Henningsson static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
55699a5592dSDavid Henningsson 			  hda_nid_t nid2, int dir)
55799a5592dSDavid Henningsson {
55899a5592dSDavid Henningsson 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
55999a5592dSDavid Henningsson 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
56099a5592dSDavid Henningsson 	return (query_amp_caps(codec, nid1, dir) ==
56199a5592dSDavid Henningsson 		query_amp_caps(codec, nid2, dir));
56299a5592dSDavid Henningsson }
56399a5592dSDavid Henningsson 
564352f7f91STakashi Iwai /* look for a widget suitable for assigning a mute switch in the path */
565352f7f91STakashi Iwai static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
566352f7f91STakashi Iwai 				       struct nid_path *path)
567352f7f91STakashi Iwai {
568352f7f91STakashi Iwai 	int i;
569352f7f91STakashi Iwai 
570352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
571352f7f91STakashi Iwai 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
572352f7f91STakashi Iwai 			return path->path[i];
573352f7f91STakashi Iwai 		if (i != path->depth - 1 && i != 0 &&
574352f7f91STakashi Iwai 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
575352f7f91STakashi Iwai 			return path->path[i];
576352f7f91STakashi Iwai 	}
577352f7f91STakashi Iwai 	return 0;
578352f7f91STakashi Iwai }
579352f7f91STakashi Iwai 
580352f7f91STakashi Iwai /* look for a widget suitable for assigning a volume ctl in the path */
581352f7f91STakashi Iwai static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
582352f7f91STakashi Iwai 				      struct nid_path *path)
583352f7f91STakashi Iwai {
584a1114a8cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
585352f7f91STakashi Iwai 	int i;
586352f7f91STakashi Iwai 
587352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
588a1114a8cSTakashi Iwai 		hda_nid_t nid = path->path[i];
589a1114a8cSTakashi Iwai 		if ((spec->out_vol_mask >> nid) & 1)
590a1114a8cSTakashi Iwai 			continue;
591a1114a8cSTakashi Iwai 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
592a1114a8cSTakashi Iwai 			return nid;
593352f7f91STakashi Iwai 	}
594352f7f91STakashi Iwai 	return 0;
595352f7f91STakashi Iwai }
596352f7f91STakashi Iwai 
597352f7f91STakashi Iwai /*
598352f7f91STakashi Iwai  * path activation / deactivation
599352f7f91STakashi Iwai  */
600352f7f91STakashi Iwai 
601352f7f91STakashi Iwai /* can have the amp-in capability? */
602352f7f91STakashi Iwai static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
603352f7f91STakashi Iwai {
604352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
605352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
606352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
607352f7f91STakashi Iwai 
608352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_IN_AMP))
609352f7f91STakashi Iwai 		return false;
610352f7f91STakashi Iwai 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
611352f7f91STakashi Iwai 		return false;
612352f7f91STakashi Iwai 	return true;
613352f7f91STakashi Iwai }
614352f7f91STakashi Iwai 
615352f7f91STakashi Iwai /* can have the amp-out capability? */
616352f7f91STakashi Iwai static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
617352f7f91STakashi Iwai {
618352f7f91STakashi Iwai 	hda_nid_t nid = path->path[idx];
619352f7f91STakashi Iwai 	unsigned int caps = get_wcaps(codec, nid);
620352f7f91STakashi Iwai 	unsigned int type = get_wcaps_type(caps);
621352f7f91STakashi Iwai 
622352f7f91STakashi Iwai 	if (!(caps & AC_WCAP_OUT_AMP))
623352f7f91STakashi Iwai 		return false;
624352f7f91STakashi Iwai 	if (type == AC_WID_PIN && !idx) /* only for output pins */
625352f7f91STakashi Iwai 		return false;
626352f7f91STakashi Iwai 	return true;
627352f7f91STakashi Iwai }
628352f7f91STakashi Iwai 
629352f7f91STakashi Iwai /* check whether the given (nid,dir,idx) is active */
630352f7f91STakashi Iwai static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
6317dddf2aeSTakashi Iwai 			  unsigned int dir, unsigned int idx)
632352f7f91STakashi Iwai {
633352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
634e6feb5d0STakashi Iwai 	int type = get_wcaps_type(get_wcaps(codec, nid));
635a9c2dfc8STakashi Iwai 	const struct nid_path *path;
636352f7f91STakashi Iwai 	int i, n;
637352f7f91STakashi Iwai 
6387639a06cSTakashi Iwai 	if (nid == codec->core.afg)
6395ccf835cSTakashi Iwai 		return true;
6405ccf835cSTakashi Iwai 
641a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, n, path) {
642352f7f91STakashi Iwai 		if (!path->active)
643352f7f91STakashi Iwai 			continue;
644967b1307STakashi Iwai 		if (codec->power_save_node) {
645e6feb5d0STakashi Iwai 			if (!path->stream_enabled)
646e6feb5d0STakashi Iwai 				continue;
647e6feb5d0STakashi Iwai 			/* ignore unplugged paths except for DAC/ADC */
6486b275b14STakashi Iwai 			if (!(path->pin_enabled || path->pin_fixed) &&
649e6feb5d0STakashi Iwai 			    type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
650e6feb5d0STakashi Iwai 				continue;
651e6feb5d0STakashi Iwai 		}
652352f7f91STakashi Iwai 		for (i = 0; i < path->depth; i++) {
653352f7f91STakashi Iwai 			if (path->path[i] == nid) {
6549d2b48f7STakashi Iwai 				if (dir == HDA_OUTPUT || idx == -1 ||
6559d2b48f7STakashi Iwai 				    path->idx[i] == idx)
656352f7f91STakashi Iwai 					return true;
657352f7f91STakashi Iwai 				break;
658352f7f91STakashi Iwai 			}
659352f7f91STakashi Iwai 		}
660352f7f91STakashi Iwai 	}
661352f7f91STakashi Iwai 	return false;
662352f7f91STakashi Iwai }
663352f7f91STakashi Iwai 
664b1b9fbd0STakashi Iwai /* check whether the NID is referred by any active paths */
665b1b9fbd0STakashi Iwai #define is_active_nid_for_any(codec, nid) \
6669d2b48f7STakashi Iwai 	is_active_nid(codec, nid, HDA_OUTPUT, -1)
667b1b9fbd0STakashi Iwai 
668352f7f91STakashi Iwai /* get the default amp value for the target state */
669352f7f91STakashi Iwai static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
6708999bf0aSTakashi Iwai 				   int dir, unsigned int caps, bool enable)
671352f7f91STakashi Iwai {
672352f7f91STakashi Iwai 	unsigned int val = 0;
673352f7f91STakashi Iwai 
674352f7f91STakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
675352f7f91STakashi Iwai 		/* set to 0dB */
676352f7f91STakashi Iwai 		if (enable)
677352f7f91STakashi Iwai 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
678352f7f91STakashi Iwai 	}
679f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
680352f7f91STakashi Iwai 		if (!enable)
681352f7f91STakashi Iwai 			val |= HDA_AMP_MUTE;
682352f7f91STakashi Iwai 	}
683352f7f91STakashi Iwai 	return val;
684352f7f91STakashi Iwai }
685352f7f91STakashi Iwai 
686cc261738STakashi Iwai /* is this a stereo widget or a stereo-to-mono mix? */
687cc261738STakashi Iwai static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
688cc261738STakashi Iwai {
689cc261738STakashi Iwai 	unsigned int wcaps = get_wcaps(codec, nid);
690cc261738STakashi Iwai 	hda_nid_t conn;
691cc261738STakashi Iwai 
692cc261738STakashi Iwai 	if (wcaps & AC_WCAP_STEREO)
693cc261738STakashi Iwai 		return true;
694cc261738STakashi Iwai 	if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
695cc261738STakashi Iwai 		return false;
696cc261738STakashi Iwai 	if (snd_hda_get_num_conns(codec, nid) != 1)
697cc261738STakashi Iwai 		return false;
698cc261738STakashi Iwai 	if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
699cc261738STakashi Iwai 		return false;
700cc261738STakashi Iwai 	return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
701cc261738STakashi Iwai }
702cc261738STakashi Iwai 
703352f7f91STakashi Iwai /* initialize the amp value (only at the first time) */
704352f7f91STakashi Iwai static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
705352f7f91STakashi Iwai {
7068999bf0aSTakashi Iwai 	unsigned int caps = query_amp_caps(codec, nid, dir);
7078999bf0aSTakashi Iwai 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
708ef403edbSTakashi Iwai 
709cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
710352f7f91STakashi Iwai 		snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
711ef403edbSTakashi Iwai 	else
712ef403edbSTakashi Iwai 		snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
713ef403edbSTakashi Iwai }
714ef403edbSTakashi Iwai 
715ef403edbSTakashi Iwai /* update the amp, doing in stereo or mono depending on NID */
716ef403edbSTakashi Iwai static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
717ef403edbSTakashi Iwai 		      unsigned int mask, unsigned int val)
718ef403edbSTakashi Iwai {
719cc261738STakashi Iwai 	if (is_stereo_amps(codec, nid, dir))
720ef403edbSTakashi Iwai 		return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
721ef403edbSTakashi Iwai 						mask, val);
722ef403edbSTakashi Iwai 	else
723ef403edbSTakashi Iwai 		return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
724ef403edbSTakashi Iwai 						mask, val);
725352f7f91STakashi Iwai }
726352f7f91STakashi Iwai 
7278999bf0aSTakashi Iwai /* calculate amp value mask we can modify;
7288999bf0aSTakashi Iwai  * if the given amp is controlled by mixers, don't touch it
7298999bf0aSTakashi Iwai  */
7308999bf0aSTakashi Iwai static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
7318999bf0aSTakashi Iwai 					   hda_nid_t nid, int dir, int idx,
7328999bf0aSTakashi Iwai 					   unsigned int caps)
733352f7f91STakashi Iwai {
7348999bf0aSTakashi Iwai 	unsigned int mask = 0xff;
7358999bf0aSTakashi Iwai 
736f69910ddSTakashi Iwai 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
7378999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
7388999bf0aSTakashi Iwai 			mask &= ~0x80;
7398999bf0aSTakashi Iwai 	}
7408999bf0aSTakashi Iwai 	if (caps & AC_AMPCAP_NUM_STEPS) {
7418999bf0aSTakashi Iwai 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
7428999bf0aSTakashi Iwai 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
7438999bf0aSTakashi Iwai 			mask &= ~0x7f;
7448999bf0aSTakashi Iwai 	}
7458999bf0aSTakashi Iwai 	return mask;
7468999bf0aSTakashi Iwai }
7478999bf0aSTakashi Iwai 
7488999bf0aSTakashi Iwai static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
7498999bf0aSTakashi Iwai 			 int idx, int idx_to_check, bool enable)
7508999bf0aSTakashi Iwai {
7518999bf0aSTakashi Iwai 	unsigned int caps;
7528999bf0aSTakashi Iwai 	unsigned int mask, val;
7538999bf0aSTakashi Iwai 
7548999bf0aSTakashi Iwai 	caps = query_amp_caps(codec, nid, dir);
7558999bf0aSTakashi Iwai 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
7568999bf0aSTakashi Iwai 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
7578999bf0aSTakashi Iwai 	if (!mask)
7588999bf0aSTakashi Iwai 		return;
7598999bf0aSTakashi Iwai 
7608999bf0aSTakashi Iwai 	val &= mask;
761ef403edbSTakashi Iwai 	update_amp(codec, nid, dir, idx, mask, val);
762352f7f91STakashi Iwai }
763352f7f91STakashi Iwai 
764e7fdd527STakashi Iwai static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
765e7fdd527STakashi Iwai 				   int dir, int idx, int idx_to_check,
766e7fdd527STakashi Iwai 				   bool enable)
767e7fdd527STakashi Iwai {
768e7fdd527STakashi Iwai 	/* check whether the given amp is still used by others */
769e7fdd527STakashi Iwai 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
770e7fdd527STakashi Iwai 		return;
771e7fdd527STakashi Iwai 	activate_amp(codec, nid, dir, idx, idx_to_check, enable);
772e7fdd527STakashi Iwai }
773e7fdd527STakashi Iwai 
774352f7f91STakashi Iwai static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
775352f7f91STakashi Iwai 			     int i, bool enable)
776352f7f91STakashi Iwai {
777352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
778352f7f91STakashi Iwai 	init_amp(codec, nid, HDA_OUTPUT, 0);
779e7fdd527STakashi Iwai 	check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
780352f7f91STakashi Iwai }
781352f7f91STakashi Iwai 
782352f7f91STakashi Iwai static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
783352f7f91STakashi Iwai 			    int i, bool enable, bool add_aamix)
784352f7f91STakashi Iwai {
785352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
786ee8e765bSTakashi Iwai 	const hda_nid_t *conn;
787352f7f91STakashi Iwai 	int n, nums, idx;
788352f7f91STakashi Iwai 	int type;
789352f7f91STakashi Iwai 	hda_nid_t nid = path->path[i];
790352f7f91STakashi Iwai 
791ee8e765bSTakashi Iwai 	nums = snd_hda_get_conn_list(codec, nid, &conn);
7920de7d835SDan Carpenter 	if (nums < 0)
7930de7d835SDan Carpenter 		return;
794352f7f91STakashi Iwai 	type = get_wcaps_type(get_wcaps(codec, nid));
795352f7f91STakashi Iwai 	if (type == AC_WID_PIN ||
796352f7f91STakashi Iwai 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
797352f7f91STakashi Iwai 		nums = 1;
798352f7f91STakashi Iwai 		idx = 0;
799352f7f91STakashi Iwai 	} else
800352f7f91STakashi Iwai 		idx = path->idx[i];
801352f7f91STakashi Iwai 
802352f7f91STakashi Iwai 	for (n = 0; n < nums; n++)
803352f7f91STakashi Iwai 		init_amp(codec, nid, HDA_INPUT, n);
804352f7f91STakashi Iwai 
805352f7f91STakashi Iwai 	/* here is a little bit tricky in comparison with activate_amp_out();
806352f7f91STakashi Iwai 	 * when aa-mixer is available, we need to enable the path as well
807352f7f91STakashi Iwai 	 */
808352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
809e7fdd527STakashi Iwai 		if (n != idx) {
810e7fdd527STakashi Iwai 			if (conn[n] != spec->mixer_merge_nid)
811352f7f91STakashi Iwai 				continue;
812e7fdd527STakashi Iwai 			/* when aamix is disabled, force to off */
813e7fdd527STakashi Iwai 			if (!add_aamix) {
814e7fdd527STakashi Iwai 				activate_amp(codec, nid, HDA_INPUT, n, n, false);
815e7fdd527STakashi Iwai 				continue;
816e7fdd527STakashi Iwai 			}
817e7fdd527STakashi Iwai 		}
818e7fdd527STakashi Iwai 		check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
819352f7f91STakashi Iwai 	}
820352f7f91STakashi Iwai }
821352f7f91STakashi Iwai 
822c7fabbc5SRandy Dunlap /* sync power of each widget in the given path */
823e6feb5d0STakashi Iwai static hda_nid_t path_power_update(struct hda_codec *codec,
824e6feb5d0STakashi Iwai 				   struct nid_path *path,
825e6feb5d0STakashi Iwai 				   bool allow_powerdown)
826e6feb5d0STakashi Iwai {
827e6feb5d0STakashi Iwai 	hda_nid_t nid, changed = 0;
82850fd4987STakashi Iwai 	int i, state, power;
829e6feb5d0STakashi Iwai 
830e6feb5d0STakashi Iwai 	for (i = 0; i < path->depth; i++) {
831e6feb5d0STakashi Iwai 		nid = path->path[i];
8322206dc94STakashi Iwai 		if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
8332206dc94STakashi Iwai 			continue;
8347639a06cSTakashi Iwai 		if (nid == codec->core.afg)
8355ccf835cSTakashi Iwai 			continue;
836e6feb5d0STakashi Iwai 		if (!allow_powerdown || is_active_nid_for_any(codec, nid))
837e6feb5d0STakashi Iwai 			state = AC_PWRST_D0;
838e6feb5d0STakashi Iwai 		else
839e6feb5d0STakashi Iwai 			state = AC_PWRST_D3;
84050fd4987STakashi Iwai 		power = snd_hda_codec_read(codec, nid, 0,
84150fd4987STakashi Iwai 					   AC_VERB_GET_POWER_STATE, 0);
84250fd4987STakashi Iwai 		if (power != (state | (state << 4))) {
843e6feb5d0STakashi Iwai 			snd_hda_codec_write(codec, nid, 0,
844e6feb5d0STakashi Iwai 					    AC_VERB_SET_POWER_STATE, state);
845e6feb5d0STakashi Iwai 			changed = nid;
84648f4b3a2STakashi Iwai 			/* all known codecs seem to be capable to handl
84748f4b3a2STakashi Iwai 			 * widgets state even in D3, so far.
84848f4b3a2STakashi Iwai 			 * if any new codecs need to restore the widget
84948f4b3a2STakashi Iwai 			 * states after D0 transition, call the function
85048f4b3a2STakashi Iwai 			 * below.
85148f4b3a2STakashi Iwai 			 */
85248f4b3a2STakashi Iwai #if 0 /* disabled */
853d545a57cSTakashi Iwai 			if (state == AC_PWRST_D0)
854d545a57cSTakashi Iwai 				snd_hdac_regmap_sync_node(&codec->core, nid);
85548f4b3a2STakashi Iwai #endif
856e6feb5d0STakashi Iwai 		}
857e6feb5d0STakashi Iwai 	}
858e6feb5d0STakashi Iwai 	return changed;
859e6feb5d0STakashi Iwai }
860e6feb5d0STakashi Iwai 
861e6feb5d0STakashi Iwai /* do sync with the last power state change */
862e6feb5d0STakashi Iwai static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
863e6feb5d0STakashi Iwai {
864e6feb5d0STakashi Iwai 	if (nid) {
865e6feb5d0STakashi Iwai 		msleep(10);
866e6feb5d0STakashi Iwai 		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
867e6feb5d0STakashi Iwai 	}
868e6feb5d0STakashi Iwai }
869e6feb5d0STakashi Iwai 
870dda42bd0STakashi Iwai /**
871dda42bd0STakashi Iwai  * snd_hda_activate_path - activate or deactivate the given path
872dda42bd0STakashi Iwai  * @codec: the HDA codec
873dda42bd0STakashi Iwai  * @path: the path to activate/deactivate
874dda42bd0STakashi Iwai  * @enable: flag to activate or not
875dda42bd0STakashi Iwai  * @add_aamix: enable the input from aamix NID
876dda42bd0STakashi Iwai  *
877dda42bd0STakashi Iwai  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
878352f7f91STakashi Iwai  */
879352f7f91STakashi Iwai void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
880352f7f91STakashi Iwai 			   bool enable, bool add_aamix)
881352f7f91STakashi Iwai {
88255196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
883352f7f91STakashi Iwai 	int i;
884352f7f91STakashi Iwai 
885c7cd0ef6STakashi Iwai 	path->active = enable;
886352f7f91STakashi Iwai 
887e6feb5d0STakashi Iwai 	/* make sure the widget is powered up */
888967b1307STakashi Iwai 	if (enable && (spec->power_down_unused || codec->power_save_node))
889967b1307STakashi Iwai 		path_power_update(codec, path, codec->power_save_node);
890e6feb5d0STakashi Iwai 
891352f7f91STakashi Iwai 	for (i = path->depth - 1; i >= 0; i--) {
89255196fffSTakashi Iwai 		hda_nid_t nid = path->path[i];
893e6feb5d0STakashi Iwai 
894352f7f91STakashi Iwai 		if (enable && path->multi[i])
895401caff7STakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
896352f7f91STakashi Iwai 					    AC_VERB_SET_CONNECT_SEL,
897352f7f91STakashi Iwai 					    path->idx[i]);
898352f7f91STakashi Iwai 		if (has_amp_in(codec, path, i))
899352f7f91STakashi Iwai 			activate_amp_in(codec, path, i, enable, add_aamix);
900352f7f91STakashi Iwai 		if (has_amp_out(codec, path, i))
901352f7f91STakashi Iwai 			activate_amp_out(codec, path, i, enable);
902352f7f91STakashi Iwai 	}
903352f7f91STakashi Iwai }
9042698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_activate_path);
905352f7f91STakashi Iwai 
90655196fffSTakashi Iwai /* if the given path is inactive, put widgets into D3 (only if suitable) */
90755196fffSTakashi Iwai static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
90855196fffSTakashi Iwai {
90955196fffSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
91055196fffSTakashi Iwai 
911967b1307STakashi Iwai 	if (!(spec->power_down_unused || codec->power_save_node) || path->active)
91255196fffSTakashi Iwai 		return;
913e6feb5d0STakashi Iwai 	sync_power_state_change(codec, path_power_update(codec, path, true));
91455196fffSTakashi Iwai }
91555196fffSTakashi Iwai 
916d5a9f1bbSTakashi Iwai /* turn on/off EAPD on the given pin */
917d5a9f1bbSTakashi Iwai static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
918d5a9f1bbSTakashi Iwai {
919d5a9f1bbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
920d5a9f1bbSTakashi Iwai 	if (spec->own_eapd_ctl ||
921d5a9f1bbSTakashi Iwai 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
922d5a9f1bbSTakashi Iwai 		return;
92305909d5cSTakashi Iwai 	if (spec->keep_eapd_on && !enable)
92405909d5cSTakashi Iwai 		return;
925468ac413STakashi Iwai 	if (codec->inv_eapd)
926468ac413STakashi Iwai 		enable = !enable;
927401caff7STakashi Iwai 	snd_hda_codec_write_cache(codec, pin, 0,
928d5a9f1bbSTakashi Iwai 				   AC_VERB_SET_EAPD_BTLENABLE,
929d5a9f1bbSTakashi Iwai 				   enable ? 0x02 : 0x00);
930d5a9f1bbSTakashi Iwai }
931d5a9f1bbSTakashi Iwai 
9323e367f15STakashi Iwai /* re-initialize the path specified by the given path index */
9333e367f15STakashi Iwai static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
9343e367f15STakashi Iwai {
9353e367f15STakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
9363e367f15STakashi Iwai 	if (path)
9373e367f15STakashi Iwai 		snd_hda_activate_path(codec, path, path->active, false);
9383e367f15STakashi Iwai }
9393e367f15STakashi Iwai 
940352f7f91STakashi Iwai 
941352f7f91STakashi Iwai /*
942352f7f91STakashi Iwai  * Helper functions for creating mixer ctl elements
943352f7f91STakashi Iwai  */
944352f7f91STakashi Iwai 
9457eebffd3STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
9467eebffd3STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol);
947698f5ee3STakashi Iwai static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
948698f5ee3STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
949bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
950bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol);
9517eebffd3STakashi Iwai 
952352f7f91STakashi Iwai enum {
953352f7f91STakashi Iwai 	HDA_CTL_WIDGET_VOL,
954352f7f91STakashi Iwai 	HDA_CTL_WIDGET_MUTE,
955352f7f91STakashi Iwai 	HDA_CTL_BIND_MUTE,
956352f7f91STakashi Iwai };
957352f7f91STakashi Iwai static const struct snd_kcontrol_new control_templates[] = {
958352f7f91STakashi Iwai 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
9597eebffd3STakashi Iwai 	/* only the put callback is replaced for handling the special mute */
9607eebffd3STakashi Iwai 	{
9617eebffd3STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
9627eebffd3STakashi Iwai 		.subdevice = HDA_SUBDEV_AMP_FLAG,
9637eebffd3STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
9647eebffd3STakashi Iwai 		.get = snd_hda_mixer_amp_switch_get,
9657eebffd3STakashi Iwai 		.put = hda_gen_mixer_mute_put, /* replaced */
9667eebffd3STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
9677eebffd3STakashi Iwai 	},
968bc2eee29STakashi Iwai 	{
969bc2eee29STakashi Iwai 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
970bc2eee29STakashi Iwai 		.info = snd_hda_mixer_amp_switch_info,
971698f5ee3STakashi Iwai 		.get = hda_gen_bind_mute_get,
972bc2eee29STakashi Iwai 		.put = hda_gen_bind_mute_put, /* replaced */
973bc2eee29STakashi Iwai 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
974bc2eee29STakashi Iwai 	},
975352f7f91STakashi Iwai };
976352f7f91STakashi Iwai 
977352f7f91STakashi Iwai /* add dynamic controls from template */
978a35bd1e3STakashi Iwai static struct snd_kcontrol_new *
979a35bd1e3STakashi Iwai add_control(struct hda_gen_spec *spec, int type, const char *name,
980352f7f91STakashi Iwai 		       int cidx, unsigned long val)
981352f7f91STakashi Iwai {
982352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
983352f7f91STakashi Iwai 
98412c93df6STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
985352f7f91STakashi Iwai 	if (!knew)
986a35bd1e3STakashi Iwai 		return NULL;
987352f7f91STakashi Iwai 	knew->index = cidx;
988352f7f91STakashi Iwai 	if (get_amp_nid_(val))
989352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
990e65bf997SJaroslav Kysela 	if (knew->access == 0)
991e65bf997SJaroslav Kysela 		knew->access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
992352f7f91STakashi Iwai 	knew->private_value = val;
993a35bd1e3STakashi Iwai 	return knew;
994352f7f91STakashi Iwai }
995352f7f91STakashi Iwai 
996352f7f91STakashi Iwai static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
997352f7f91STakashi Iwai 				const char *pfx, const char *dir,
998352f7f91STakashi Iwai 				const char *sfx, int cidx, unsigned long val)
999352f7f91STakashi Iwai {
1000975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
10015f6af005STakashi Iwai 	int len;
10025f6af005STakashi Iwai 
10035f6af005STakashi Iwai 	len = snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
10045f6af005STakashi Iwai 	if (snd_BUG_ON(len >= sizeof(name)))
10055f6af005STakashi Iwai 		return -EINVAL;
1006a35bd1e3STakashi Iwai 	if (!add_control(spec, type, name, cidx, val))
1007a35bd1e3STakashi Iwai 		return -ENOMEM;
1008a35bd1e3STakashi Iwai 	return 0;
1009352f7f91STakashi Iwai }
1010352f7f91STakashi Iwai 
1011352f7f91STakashi Iwai #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1012352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1013352f7f91STakashi Iwai #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1014352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1015352f7f91STakashi Iwai #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1016352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1017352f7f91STakashi Iwai #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1018352f7f91STakashi Iwai 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1019352f7f91STakashi Iwai 
1020352f7f91STakashi Iwai static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1021352f7f91STakashi Iwai 		       unsigned int chs, struct nid_path *path)
1022352f7f91STakashi Iwai {
1023352f7f91STakashi Iwai 	unsigned int val;
1024352f7f91STakashi Iwai 	if (!path)
1025352f7f91STakashi Iwai 		return 0;
1026352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_VOL_CTL];
1027352f7f91STakashi Iwai 	if (!val)
1028352f7f91STakashi Iwai 		return 0;
1029352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1030352f7f91STakashi Iwai 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1031352f7f91STakashi Iwai }
1032352f7f91STakashi Iwai 
1033352f7f91STakashi Iwai /* return the channel bits suitable for the given path->ctls[] */
1034352f7f91STakashi Iwai static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1035352f7f91STakashi Iwai 			       int type)
1036352f7f91STakashi Iwai {
1037352f7f91STakashi Iwai 	int chs = 1; /* mono (left only) */
1038352f7f91STakashi Iwai 	if (path) {
1039352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1040352f7f91STakashi Iwai 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1041352f7f91STakashi Iwai 			chs = 3; /* stereo */
1042352f7f91STakashi Iwai 	}
1043352f7f91STakashi Iwai 	return chs;
1044352f7f91STakashi Iwai }
1045352f7f91STakashi Iwai 
1046352f7f91STakashi Iwai static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1047352f7f91STakashi Iwai 			  struct nid_path *path)
1048352f7f91STakashi Iwai {
1049352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1050352f7f91STakashi Iwai 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1051352f7f91STakashi Iwai }
1052352f7f91STakashi Iwai 
1053352f7f91STakashi Iwai /* create a mute-switch for the given mixer widget;
1054352f7f91STakashi Iwai  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1055352f7f91STakashi Iwai  */
1056352f7f91STakashi Iwai static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1057352f7f91STakashi Iwai 		      unsigned int chs, struct nid_path *path)
1058352f7f91STakashi Iwai {
1059352f7f91STakashi Iwai 	unsigned int val;
1060352f7f91STakashi Iwai 	int type = HDA_CTL_WIDGET_MUTE;
1061352f7f91STakashi Iwai 
1062352f7f91STakashi Iwai 	if (!path)
1063352f7f91STakashi Iwai 		return 0;
1064352f7f91STakashi Iwai 	val = path->ctls[NID_PATH_MUTE_CTL];
1065352f7f91STakashi Iwai 	if (!val)
1066352f7f91STakashi Iwai 		return 0;
1067352f7f91STakashi Iwai 	val = amp_val_replace_channels(val, chs);
1068352f7f91STakashi Iwai 	if (get_amp_direction_(val) == HDA_INPUT) {
1069352f7f91STakashi Iwai 		hda_nid_t nid = get_amp_nid_(val);
1070352f7f91STakashi Iwai 		int nums = snd_hda_get_num_conns(codec, nid);
1071352f7f91STakashi Iwai 		if (nums > 1) {
1072352f7f91STakashi Iwai 			type = HDA_CTL_BIND_MUTE;
1073352f7f91STakashi Iwai 			val |= nums << 19;
1074352f7f91STakashi Iwai 		}
1075352f7f91STakashi Iwai 	}
1076352f7f91STakashi Iwai 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1077352f7f91STakashi Iwai }
1078352f7f91STakashi Iwai 
1079352f7f91STakashi Iwai static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1080352f7f91STakashi Iwai 				  int cidx, struct nid_path *path)
1081352f7f91STakashi Iwai {
1082352f7f91STakashi Iwai 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1083352f7f91STakashi Iwai 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1084352f7f91STakashi Iwai }
1085352f7f91STakashi Iwai 
10867eebffd3STakashi Iwai /* playback mute control with the software mute bit check */
1087bc2eee29STakashi Iwai static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
10887eebffd3STakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
10897eebffd3STakashi Iwai {
10907eebffd3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
10917eebffd3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
10927eebffd3STakashi Iwai 
10937eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp) {
10947eebffd3STakashi Iwai 		hda_nid_t nid = get_amp_nid(kcontrol);
10957eebffd3STakashi Iwai 		bool enabled = !((spec->mute_bits >> nid) & 1);
10967eebffd3STakashi Iwai 		ucontrol->value.integer.value[0] &= enabled;
10977eebffd3STakashi Iwai 		ucontrol->value.integer.value[1] &= enabled;
10987eebffd3STakashi Iwai 	}
1099bc2eee29STakashi Iwai }
11007eebffd3STakashi Iwai 
1101bc2eee29STakashi Iwai static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1102bc2eee29STakashi Iwai 				  struct snd_ctl_elem_value *ucontrol)
1103bc2eee29STakashi Iwai {
1104bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
11057eebffd3STakashi Iwai 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
11067eebffd3STakashi Iwai }
11077eebffd3STakashi Iwai 
1108698f5ee3STakashi Iwai /*
1109698f5ee3STakashi Iwai  * Bound mute controls
1110698f5ee3STakashi Iwai  */
1111698f5ee3STakashi Iwai #define AMP_VAL_IDX_SHIFT	19
1112698f5ee3STakashi Iwai #define AMP_VAL_IDX_MASK	(0x0f<<19)
1113698f5ee3STakashi Iwai 
1114698f5ee3STakashi Iwai static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
1115698f5ee3STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1116698f5ee3STakashi Iwai {
1117698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1118698f5ee3STakashi Iwai 	unsigned long pval;
1119698f5ee3STakashi Iwai 	int err;
1120698f5ee3STakashi Iwai 
1121698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1122698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1123698f5ee3STakashi Iwai 	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1124698f5ee3STakashi Iwai 	err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1125698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1126698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1127698f5ee3STakashi Iwai 	return err;
1128698f5ee3STakashi Iwai }
1129698f5ee3STakashi Iwai 
1130bc2eee29STakashi Iwai static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1131bc2eee29STakashi Iwai 				 struct snd_ctl_elem_value *ucontrol)
1132bc2eee29STakashi Iwai {
1133698f5ee3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1134698f5ee3STakashi Iwai 	unsigned long pval;
1135698f5ee3STakashi Iwai 	int i, indices, err = 0, change = 0;
1136698f5ee3STakashi Iwai 
1137bc2eee29STakashi Iwai 	sync_auto_mute_bits(kcontrol, ucontrol);
1138698f5ee3STakashi Iwai 
1139698f5ee3STakashi Iwai 	mutex_lock(&codec->control_mutex);
1140698f5ee3STakashi Iwai 	pval = kcontrol->private_value;
1141698f5ee3STakashi Iwai 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1142698f5ee3STakashi Iwai 	for (i = 0; i < indices; i++) {
1143698f5ee3STakashi Iwai 		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1144698f5ee3STakashi Iwai 			(i << AMP_VAL_IDX_SHIFT);
1145698f5ee3STakashi Iwai 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1146698f5ee3STakashi Iwai 		if (err < 0)
1147698f5ee3STakashi Iwai 			break;
1148698f5ee3STakashi Iwai 		change |= err;
1149698f5ee3STakashi Iwai 	}
1150698f5ee3STakashi Iwai 	kcontrol->private_value = pval;
1151698f5ee3STakashi Iwai 	mutex_unlock(&codec->control_mutex);
1152698f5ee3STakashi Iwai 	return err < 0 ? err : change;
1153bc2eee29STakashi Iwai }
1154bc2eee29STakashi Iwai 
1155247d85eeSTakashi Iwai /* any ctl assigned to the path with the given index? */
1156247d85eeSTakashi Iwai static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1157247d85eeSTakashi Iwai {
1158247d85eeSTakashi Iwai 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1159247d85eeSTakashi Iwai 	return path && path->ctls[ctl_type];
1160247d85eeSTakashi Iwai }
1161247d85eeSTakashi Iwai 
11623b44ec8cSTakashi Iwai static const char * const channel_name[] = {
11633b44ec8cSTakashi Iwai 	"Front", "Surround", "CLFE", "Side", "Back",
1164352f7f91STakashi Iwai };
1165352f7f91STakashi Iwai 
1166352f7f91STakashi Iwai /* give some appropriate ctl name prefix for the given line out channel */
1167247d85eeSTakashi Iwai static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1168247d85eeSTakashi Iwai 				    int *index, int ctl_type)
1169352f7f91STakashi Iwai {
1170247d85eeSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1171352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1172352f7f91STakashi Iwai 
1173352f7f91STakashi Iwai 	*index = 0;
1174352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios &&
11759f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1176247d85eeSTakashi Iwai 	    !cfg->hp_outs && !cfg->speaker_outs)
1177352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1178352f7f91STakashi Iwai 
1179352f7f91STakashi Iwai 	/* if there is really a single DAC used in the whole output paths,
1180352f7f91STakashi Iwai 	 * use it master (or "PCM" if a vmaster hook is present)
1181352f7f91STakashi Iwai 	 */
1182352f7f91STakashi Iwai 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
11839f3dadb1STakashi Iwai 	    !codec->force_pin_prefix &&
1184352f7f91STakashi Iwai 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1185352f7f91STakashi Iwai 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1186352f7f91STakashi Iwai 
1187247d85eeSTakashi Iwai 	/* multi-io channels */
1188247d85eeSTakashi Iwai 	if (ch >= cfg->line_outs)
11893b44ec8cSTakashi Iwai 		goto fixed_name;
1190247d85eeSTakashi Iwai 
1191352f7f91STakashi Iwai 	switch (cfg->line_out_type) {
1192352f7f91STakashi Iwai 	case AUTO_PIN_SPEAKER_OUT:
1193247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with HP volume,
1194247d85eeSTakashi Iwai 		 * don't name it as Speaker
1195247d85eeSTakashi Iwai 		 */
1196247d85eeSTakashi Iwai 		if (!ch && cfg->hp_outs &&
1197247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1198247d85eeSTakashi Iwai 			break;
1199352f7f91STakashi Iwai 		if (cfg->line_outs == 1)
1200352f7f91STakashi Iwai 			return "Speaker";
1201352f7f91STakashi Iwai 		if (cfg->line_outs == 2)
1202352f7f91STakashi Iwai 			return ch ? "Bass Speaker" : "Speaker";
1203352f7f91STakashi Iwai 		break;
1204352f7f91STakashi Iwai 	case AUTO_PIN_HP_OUT:
1205247d85eeSTakashi Iwai 		/* if the primary channel vol/mute is shared with spk volume,
1206247d85eeSTakashi Iwai 		 * don't name it as Headphone
1207247d85eeSTakashi Iwai 		 */
1208247d85eeSTakashi Iwai 		if (!ch && cfg->speaker_outs &&
1209247d85eeSTakashi Iwai 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1210247d85eeSTakashi Iwai 			break;
1211352f7f91STakashi Iwai 		/* for multi-io case, only the primary out */
1212352f7f91STakashi Iwai 		if (ch && spec->multi_ios)
1213352f7f91STakashi Iwai 			break;
1214352f7f91STakashi Iwai 		*index = ch;
1215352f7f91STakashi Iwai 		return "Headphone";
121603ad6a8cSDavid Henningsson 	case AUTO_PIN_LINE_OUT:
1217f48652bbSHui Wang 		/* This deals with the case where one HP or one Speaker or
1218f48652bbSHui Wang 		 * one HP + one Speaker need to share the DAC with LO
1219f48652bbSHui Wang 		 */
1220f48652bbSHui Wang 		if (!ch) {
1221f48652bbSHui Wang 			bool hp_lo_shared = false, spk_lo_shared = false;
1222f48652bbSHui Wang 
1223f48652bbSHui Wang 			if (cfg->speaker_outs)
1224f48652bbSHui Wang 				spk_lo_shared = !path_has_mixer(codec,
1225f48652bbSHui Wang 								spec->speaker_paths[0],	ctl_type);
1226f48652bbSHui Wang 			if (cfg->hp_outs)
1227f48652bbSHui Wang 				hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
122803ad6a8cSDavid Henningsson 			if (hp_lo_shared && spk_lo_shared)
122903ad6a8cSDavid Henningsson 				return spec->vmaster_mute.hook ? "PCM" : "Master";
123003ad6a8cSDavid Henningsson 			if (hp_lo_shared)
123103ad6a8cSDavid Henningsson 				return "Headphone+LO";
123203ad6a8cSDavid Henningsson 			if (spk_lo_shared)
123303ad6a8cSDavid Henningsson 				return "Speaker+LO";
123403ad6a8cSDavid Henningsson 		}
1235247d85eeSTakashi Iwai 	}
1236247d85eeSTakashi Iwai 
1237247d85eeSTakashi Iwai 	/* for a single channel output, we don't have to name the channel */
1238352f7f91STakashi Iwai 	if (cfg->line_outs == 1 && !spec->multi_ios)
12393abb4f4dSDavid Henningsson 		return "Line Out";
1240247d85eeSTakashi Iwai 
12413b44ec8cSTakashi Iwai  fixed_name:
1242352f7f91STakashi Iwai 	if (ch >= ARRAY_SIZE(channel_name)) {
1243352f7f91STakashi Iwai 		snd_BUG();
1244352f7f91STakashi Iwai 		return "PCM";
1245352f7f91STakashi Iwai 	}
1246352f7f91STakashi Iwai 
1247352f7f91STakashi Iwai 	return channel_name[ch];
1248352f7f91STakashi Iwai }
1249352f7f91STakashi Iwai 
1250352f7f91STakashi Iwai /*
1251352f7f91STakashi Iwai  * Parse output paths
1252352f7f91STakashi Iwai  */
1253352f7f91STakashi Iwai 
1254352f7f91STakashi Iwai /* badness definition */
1255352f7f91STakashi Iwai enum {
1256352f7f91STakashi Iwai 	/* No primary DAC is found for the main output */
1257352f7f91STakashi Iwai 	BAD_NO_PRIMARY_DAC = 0x10000,
1258352f7f91STakashi Iwai 	/* No DAC is found for the extra output */
1259352f7f91STakashi Iwai 	BAD_NO_DAC = 0x4000,
1260352f7f91STakashi Iwai 	/* No possible multi-ios */
12611d739066STakashi Iwai 	BAD_MULTI_IO = 0x120,
1262352f7f91STakashi Iwai 	/* No individual DAC for extra output */
1263352f7f91STakashi Iwai 	BAD_NO_EXTRA_DAC = 0x102,
1264352f7f91STakashi Iwai 	/* No individual DAC for extra surrounds */
1265352f7f91STakashi Iwai 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1266352f7f91STakashi Iwai 	/* Primary DAC shared with main surrounds */
1267352f7f91STakashi Iwai 	BAD_SHARED_SURROUND = 0x100,
126855a63d4dSTakashi Iwai 	/* No independent HP possible */
1269bec8e680STakashi Iwai 	BAD_NO_INDEP_HP = 0x10,
1270352f7f91STakashi Iwai 	/* Primary DAC shared with main CLFE */
1271352f7f91STakashi Iwai 	BAD_SHARED_CLFE = 0x10,
1272352f7f91STakashi Iwai 	/* Primary DAC shared with extra surrounds */
1273352f7f91STakashi Iwai 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1274352f7f91STakashi Iwai 	/* Volume widget is shared */
1275352f7f91STakashi Iwai 	BAD_SHARED_VOL = 0x10,
1276352f7f91STakashi Iwai };
1277352f7f91STakashi Iwai 
12780e614dd0STakashi Iwai /* look for widgets in the given path which are appropriate for
1279352f7f91STakashi Iwai  * volume and mute controls, and assign the values to ctls[].
1280352f7f91STakashi Iwai  *
1281352f7f91STakashi Iwai  * When no appropriate widget is found in the path, the badness value
1282352f7f91STakashi Iwai  * is incremented depending on the situation.  The function returns the
1283352f7f91STakashi Iwai  * total badness for both volume and mute controls.
1284352f7f91STakashi Iwai  */
12850e614dd0STakashi Iwai static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1286352f7f91STakashi Iwai {
1287d89c6c0cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1288352f7f91STakashi Iwai 	hda_nid_t nid;
1289352f7f91STakashi Iwai 	unsigned int val;
1290352f7f91STakashi Iwai 	int badness = 0;
1291352f7f91STakashi Iwai 
1292352f7f91STakashi Iwai 	if (!path)
1293352f7f91STakashi Iwai 		return BAD_SHARED_VOL * 2;
12940e614dd0STakashi Iwai 
12950e614dd0STakashi Iwai 	if (path->ctls[NID_PATH_VOL_CTL] ||
12960e614dd0STakashi Iwai 	    path->ctls[NID_PATH_MUTE_CTL])
12970e614dd0STakashi Iwai 		return 0; /* already evaluated */
12980e614dd0STakashi Iwai 
1299352f7f91STakashi Iwai 	nid = look_for_out_vol_nid(codec, path);
1300352f7f91STakashi Iwai 	if (nid) {
1301352f7f91STakashi Iwai 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1302d89c6c0cSTakashi Iwai 		if (spec->dac_min_mute)
1303d89c6c0cSTakashi Iwai 			val |= HDA_AMP_VAL_MIN_MUTE;
1304352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1305352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1306352f7f91STakashi Iwai 		else
1307352f7f91STakashi Iwai 			path->ctls[NID_PATH_VOL_CTL] = val;
1308352f7f91STakashi Iwai 	} else
1309352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1310352f7f91STakashi Iwai 	nid = look_for_out_mute_nid(codec, path);
1311352f7f91STakashi Iwai 	if (nid) {
1312352f7f91STakashi Iwai 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1313352f7f91STakashi Iwai 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1314352f7f91STakashi Iwai 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1315352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1316352f7f91STakashi Iwai 		else
1317352f7f91STakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1318352f7f91STakashi Iwai 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1319352f7f91STakashi Iwai 			badness += BAD_SHARED_VOL;
1320352f7f91STakashi Iwai 		else
1321352f7f91STakashi Iwai 			path->ctls[NID_PATH_MUTE_CTL] = val;
1322352f7f91STakashi Iwai 	} else
1323352f7f91STakashi Iwai 		badness += BAD_SHARED_VOL;
1324352f7f91STakashi Iwai 	return badness;
1325352f7f91STakashi Iwai }
1326352f7f91STakashi Iwai 
132798bd1115STakashi Iwai const struct badness_table hda_main_out_badness = {
1328352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1329352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1330352f7f91STakashi Iwai 	.shared_primary = BAD_NO_PRIMARY_DAC,
1331352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_SURROUND,
1332352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_CLFE,
1333352f7f91STakashi Iwai 	.shared_surr_main = BAD_SHARED_SURROUND,
1334352f7f91STakashi Iwai };
13352698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_main_out_badness);
1336352f7f91STakashi Iwai 
133798bd1115STakashi Iwai const struct badness_table hda_extra_out_badness = {
1338352f7f91STakashi Iwai 	.no_primary_dac = BAD_NO_DAC,
1339352f7f91STakashi Iwai 	.no_dac = BAD_NO_DAC,
1340352f7f91STakashi Iwai 	.shared_primary = BAD_NO_EXTRA_DAC,
1341352f7f91STakashi Iwai 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1342352f7f91STakashi Iwai 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1343352f7f91STakashi Iwai 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1344352f7f91STakashi Iwai };
13452698ea98STakashi Iwai EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1346352f7f91STakashi Iwai 
13477385df61STakashi Iwai /* get the DAC of the primary output corresponding to the given array index */
13487385df61STakashi Iwai static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
13497385df61STakashi Iwai {
13507385df61STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
13517385df61STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
13527385df61STakashi Iwai 
13537385df61STakashi Iwai 	if (cfg->line_outs > idx)
13547385df61STakashi Iwai 		return spec->private_dac_nids[idx];
13557385df61STakashi Iwai 	idx -= cfg->line_outs;
13567385df61STakashi Iwai 	if (spec->multi_ios > idx)
13577385df61STakashi Iwai 		return spec->multi_io[idx].dac;
13587385df61STakashi Iwai 	return 0;
13597385df61STakashi Iwai }
13607385df61STakashi Iwai 
13617385df61STakashi Iwai /* return the DAC if it's reachable, otherwise zero */
13627385df61STakashi Iwai static inline hda_nid_t try_dac(struct hda_codec *codec,
13637385df61STakashi Iwai 				hda_nid_t dac, hda_nid_t pin)
13647385df61STakashi Iwai {
13657385df61STakashi Iwai 	return is_reachable_path(codec, dac, pin) ? dac : 0;
13667385df61STakashi Iwai }
13677385df61STakashi Iwai 
1368352f7f91STakashi Iwai /* try to assign DACs to pins and return the resultant badness */
1369352f7f91STakashi Iwai static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1370352f7f91STakashi Iwai 			   const hda_nid_t *pins, hda_nid_t *dacs,
1371196c1766STakashi Iwai 			   int *path_idx,
1372352f7f91STakashi Iwai 			   const struct badness_table *bad)
1373352f7f91STakashi Iwai {
1374352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1375352f7f91STakashi Iwai 	int i, j;
1376352f7f91STakashi Iwai 	int badness = 0;
1377352f7f91STakashi Iwai 	hda_nid_t dac;
1378352f7f91STakashi Iwai 
1379352f7f91STakashi Iwai 	if (!num_outs)
1380352f7f91STakashi Iwai 		return 0;
1381352f7f91STakashi Iwai 
1382352f7f91STakashi Iwai 	for (i = 0; i < num_outs; i++) {
13830c8c0f56STakashi Iwai 		struct nid_path *path;
1384352f7f91STakashi Iwai 		hda_nid_t pin = pins[i];
13851e0b5286STakashi Iwai 
1386*1c801e7fSTakashi Iwai 		if (!spec->preferred_dacs) {
13870e614dd0STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, path_idx[i]);
13880e614dd0STakashi Iwai 			if (path) {
13890e614dd0STakashi Iwai 				badness += assign_out_path_ctls(codec, path);
13901e0b5286STakashi Iwai 				continue;
13911e0b5286STakashi Iwai 			}
1392242d990cSTakashi Iwai 		}
13931e0b5286STakashi Iwai 
13943690739bSTakashi Iwai 		dacs[i] = get_preferred_dac(codec, pin);
13953690739bSTakashi Iwai 		if (dacs[i]) {
13963690739bSTakashi Iwai 			if (is_dac_already_used(codec, dacs[i]))
13973690739bSTakashi Iwai 				badness += bad->shared_primary;
1398*1c801e7fSTakashi Iwai 		} else if (spec->preferred_dacs) {
1399242d990cSTakashi Iwai 			badness += BAD_NO_PRIMARY_DAC;
14003690739bSTakashi Iwai 		}
14013690739bSTakashi Iwai 
14023690739bSTakashi Iwai 		if (!dacs[i])
1403352f7f91STakashi Iwai 			dacs[i] = look_for_dac(codec, pin, false);
1404352f7f91STakashi Iwai 		if (!dacs[i] && !i) {
1405980428ceSTakashi Iwai 			/* try to steal the DAC of surrounds for the front */
1406352f7f91STakashi Iwai 			for (j = 1; j < num_outs; j++) {
1407352f7f91STakashi Iwai 				if (is_reachable_path(codec, dacs[j], pin)) {
1408352f7f91STakashi Iwai 					dacs[0] = dacs[j];
1409352f7f91STakashi Iwai 					dacs[j] = 0;
1410980428ceSTakashi Iwai 					invalidate_nid_path(codec, path_idx[j]);
1411196c1766STakashi Iwai 					path_idx[j] = 0;
1412352f7f91STakashi Iwai 					break;
1413352f7f91STakashi Iwai 				}
1414352f7f91STakashi Iwai 			}
1415352f7f91STakashi Iwai 		}
1416352f7f91STakashi Iwai 		dac = dacs[i];
1417352f7f91STakashi Iwai 		if (!dac) {
14187385df61STakashi Iwai 			if (num_outs > 2)
14197385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
14207385df61STakashi Iwai 			if (!dac)
14217385df61STakashi Iwai 				dac = try_dac(codec, dacs[0], pin);
14227385df61STakashi Iwai 			if (!dac)
14237385df61STakashi Iwai 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1424352f7f91STakashi Iwai 			if (dac) {
1425352f7f91STakashi Iwai 				if (!i)
1426352f7f91STakashi Iwai 					badness += bad->shared_primary;
1427352f7f91STakashi Iwai 				else if (i == 1)
1428352f7f91STakashi Iwai 					badness += bad->shared_surr;
1429352f7f91STakashi Iwai 				else
1430352f7f91STakashi Iwai 					badness += bad->shared_clfe;
1431352f7f91STakashi Iwai 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1432352f7f91STakashi Iwai 				dac = spec->private_dac_nids[0];
1433352f7f91STakashi Iwai 				badness += bad->shared_surr_main;
1434352f7f91STakashi Iwai 			} else if (!i)
1435352f7f91STakashi Iwai 				badness += bad->no_primary_dac;
1436352f7f91STakashi Iwai 			else
1437352f7f91STakashi Iwai 				badness += bad->no_dac;
1438352f7f91STakashi Iwai 		}
14391fa335b0STakashi Iwai 		if (!dac)
14401fa335b0STakashi Iwai 			continue;
14413ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1442117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid) {
1443b3a8c745STakashi Iwai 			/* try with aamix */
14443ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1445b3a8c745STakashi Iwai 		}
14461fa335b0STakashi Iwai 		if (!path) {
1447e73b4c9eSJiapeng Chong 			dacs[i] = 0;
14481fa335b0STakashi Iwai 			badness += bad->no_dac;
14491fa335b0STakashi Iwai 		} else {
14504e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1451e1284af7STakashi Iwai 			path->active = true;
1452196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
14530e614dd0STakashi Iwai 			badness += assign_out_path_ctls(codec, path);
1454e1284af7STakashi Iwai 		}
1455352f7f91STakashi Iwai 	}
1456352f7f91STakashi Iwai 
1457352f7f91STakashi Iwai 	return badness;
1458352f7f91STakashi Iwai }
1459352f7f91STakashi Iwai 
1460352f7f91STakashi Iwai /* return NID if the given pin has only a single connection to a certain DAC */
1461352f7f91STakashi Iwai static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1462352f7f91STakashi Iwai {
1463352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1464352f7f91STakashi Iwai 	int i;
1465352f7f91STakashi Iwai 	hda_nid_t nid_found = 0;
1466352f7f91STakashi Iwai 
1467352f7f91STakashi Iwai 	for (i = 0; i < spec->num_all_dacs; i++) {
1468352f7f91STakashi Iwai 		hda_nid_t nid = spec->all_dacs[i];
1469352f7f91STakashi Iwai 		if (!nid || is_dac_already_used(codec, nid))
1470352f7f91STakashi Iwai 			continue;
1471352f7f91STakashi Iwai 		if (is_reachable_path(codec, nid, pin)) {
1472352f7f91STakashi Iwai 			if (nid_found)
1473352f7f91STakashi Iwai 				return 0;
1474352f7f91STakashi Iwai 			nid_found = nid;
1475352f7f91STakashi Iwai 		}
1476352f7f91STakashi Iwai 	}
1477352f7f91STakashi Iwai 	return nid_found;
1478352f7f91STakashi Iwai }
1479352f7f91STakashi Iwai 
1480352f7f91STakashi Iwai /* check whether the given pin can be a multi-io pin */
1481352f7f91STakashi Iwai static bool can_be_multiio_pin(struct hda_codec *codec,
1482352f7f91STakashi Iwai 			       unsigned int location, hda_nid_t nid)
1483352f7f91STakashi Iwai {
1484352f7f91STakashi Iwai 	unsigned int defcfg, caps;
1485352f7f91STakashi Iwai 
1486352f7f91STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1487352f7f91STakashi Iwai 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1488352f7f91STakashi Iwai 		return false;
1489352f7f91STakashi Iwai 	if (location && get_defcfg_location(defcfg) != location)
1490352f7f91STakashi Iwai 		return false;
1491352f7f91STakashi Iwai 	caps = snd_hda_query_pin_caps(codec, nid);
1492352f7f91STakashi Iwai 	if (!(caps & AC_PINCAP_OUT))
1493352f7f91STakashi Iwai 		return false;
1494352f7f91STakashi Iwai 	return true;
1495352f7f91STakashi Iwai }
1496352f7f91STakashi Iwai 
1497e22aab7dSTakashi Iwai /* count the number of input pins that are capable to be multi-io */
1498e22aab7dSTakashi Iwai static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1499e22aab7dSTakashi Iwai {
1500e22aab7dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1501e22aab7dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1502e22aab7dSTakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1503e22aab7dSTakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1504e22aab7dSTakashi Iwai 	int type, i;
1505e22aab7dSTakashi Iwai 	int num_pins = 0;
1506e22aab7dSTakashi Iwai 
1507e22aab7dSTakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1508e22aab7dSTakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1509e22aab7dSTakashi Iwai 			if (cfg->inputs[i].type != type)
1510e22aab7dSTakashi Iwai 				continue;
1511e22aab7dSTakashi Iwai 			if (can_be_multiio_pin(codec, location,
1512e22aab7dSTakashi Iwai 					       cfg->inputs[i].pin))
1513e22aab7dSTakashi Iwai 				num_pins++;
1514e22aab7dSTakashi Iwai 		}
1515e22aab7dSTakashi Iwai 	}
1516e22aab7dSTakashi Iwai 	return num_pins;
1517e22aab7dSTakashi Iwai }
1518e22aab7dSTakashi Iwai 
1519352f7f91STakashi Iwai /*
1520352f7f91STakashi Iwai  * multi-io helper
1521352f7f91STakashi Iwai  *
1522352f7f91STakashi Iwai  * When hardwired is set, try to fill ony hardwired pins, and returns
1523352f7f91STakashi Iwai  * zero if any pins are filled, non-zero if nothing found.
1524352f7f91STakashi Iwai  * When hardwired is off, try to fill possible input pins, and returns
1525352f7f91STakashi Iwai  * the badness value.
1526352f7f91STakashi Iwai  */
1527352f7f91STakashi Iwai static int fill_multi_ios(struct hda_codec *codec,
1528352f7f91STakashi Iwai 			  hda_nid_t reference_pin,
1529e22aab7dSTakashi Iwai 			  bool hardwired)
1530352f7f91STakashi Iwai {
1531352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1532352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1533e22aab7dSTakashi Iwai 	int type, i, j, num_pins, old_pins;
1534352f7f91STakashi Iwai 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1535352f7f91STakashi Iwai 	unsigned int location = get_defcfg_location(defcfg);
1536352f7f91STakashi Iwai 	int badness = 0;
15370e614dd0STakashi Iwai 	struct nid_path *path;
1538352f7f91STakashi Iwai 
1539352f7f91STakashi Iwai 	old_pins = spec->multi_ios;
1540352f7f91STakashi Iwai 	if (old_pins >= 2)
1541352f7f91STakashi Iwai 		goto end_fill;
1542352f7f91STakashi Iwai 
1543e22aab7dSTakashi Iwai 	num_pins = count_multiio_pins(codec, reference_pin);
1544352f7f91STakashi Iwai 	if (num_pins < 2)
1545352f7f91STakashi Iwai 		goto end_fill;
1546352f7f91STakashi Iwai 
1547352f7f91STakashi Iwai 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1548352f7f91STakashi Iwai 		for (i = 0; i < cfg->num_inputs; i++) {
1549352f7f91STakashi Iwai 			hda_nid_t nid = cfg->inputs[i].pin;
1550352f7f91STakashi Iwai 			hda_nid_t dac = 0;
1551352f7f91STakashi Iwai 
1552352f7f91STakashi Iwai 			if (cfg->inputs[i].type != type)
1553352f7f91STakashi Iwai 				continue;
1554352f7f91STakashi Iwai 			if (!can_be_multiio_pin(codec, location, nid))
1555352f7f91STakashi Iwai 				continue;
1556352f7f91STakashi Iwai 			for (j = 0; j < spec->multi_ios; j++) {
1557352f7f91STakashi Iwai 				if (nid == spec->multi_io[j].pin)
1558352f7f91STakashi Iwai 					break;
1559352f7f91STakashi Iwai 			}
1560352f7f91STakashi Iwai 			if (j < spec->multi_ios)
1561352f7f91STakashi Iwai 				continue;
1562352f7f91STakashi Iwai 
1563352f7f91STakashi Iwai 			if (hardwired)
1564352f7f91STakashi Iwai 				dac = get_dac_if_single(codec, nid);
1565352f7f91STakashi Iwai 			else if (!dac)
1566352f7f91STakashi Iwai 				dac = look_for_dac(codec, nid, false);
1567352f7f91STakashi Iwai 			if (!dac) {
1568352f7f91STakashi Iwai 				badness++;
1569352f7f91STakashi Iwai 				continue;
1570352f7f91STakashi Iwai 			}
15713ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, nid,
15723ca529d3STakashi Iwai 						    -spec->mixer_nid);
15730c8c0f56STakashi Iwai 			if (!path) {
1574352f7f91STakashi Iwai 				badness++;
1575352f7f91STakashi Iwai 				continue;
1576352f7f91STakashi Iwai 			}
15774e76a883STakashi Iwai 			/* print_nid_path(codec, "multiio", path); */
1578352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].pin = nid;
1579352f7f91STakashi Iwai 			spec->multi_io[spec->multi_ios].dac = dac;
1580196c1766STakashi Iwai 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1581196c1766STakashi Iwai 				snd_hda_get_path_idx(codec, path);
1582352f7f91STakashi Iwai 			spec->multi_ios++;
1583352f7f91STakashi Iwai 			if (spec->multi_ios >= 2)
1584352f7f91STakashi Iwai 				break;
1585352f7f91STakashi Iwai 		}
1586352f7f91STakashi Iwai 	}
1587352f7f91STakashi Iwai  end_fill:
1588352f7f91STakashi Iwai 	if (badness)
1589352f7f91STakashi Iwai 		badness = BAD_MULTI_IO;
1590352f7f91STakashi Iwai 	if (old_pins == spec->multi_ios) {
1591352f7f91STakashi Iwai 		if (hardwired)
1592352f7f91STakashi Iwai 			return 1; /* nothing found */
1593352f7f91STakashi Iwai 		else
1594352f7f91STakashi Iwai 			return badness; /* no badness if nothing found */
1595352f7f91STakashi Iwai 	}
1596352f7f91STakashi Iwai 	if (!hardwired && spec->multi_ios < 2) {
1597352f7f91STakashi Iwai 		/* cancel newly assigned paths */
1598352f7f91STakashi Iwai 		spec->paths.used -= spec->multi_ios - old_pins;
1599352f7f91STakashi Iwai 		spec->multi_ios = old_pins;
1600352f7f91STakashi Iwai 		return badness;
1601352f7f91STakashi Iwai 	}
1602352f7f91STakashi Iwai 
1603352f7f91STakashi Iwai 	/* assign volume and mute controls */
16040e614dd0STakashi Iwai 	for (i = old_pins; i < spec->multi_ios; i++) {
16050e614dd0STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
16060e614dd0STakashi Iwai 		badness += assign_out_path_ctls(codec, path);
16070e614dd0STakashi Iwai 	}
1608352f7f91STakashi Iwai 
1609352f7f91STakashi Iwai 	return badness;
1610352f7f91STakashi Iwai }
1611352f7f91STakashi Iwai 
1612352f7f91STakashi Iwai /* map DACs for all pins in the list if they are single connections */
1613352f7f91STakashi Iwai static bool map_singles(struct hda_codec *codec, int outs,
1614196c1766STakashi Iwai 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1615352f7f91STakashi Iwai {
1616b3a8c745STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1617352f7f91STakashi Iwai 	int i;
1618352f7f91STakashi Iwai 	bool found = false;
1619352f7f91STakashi Iwai 	for (i = 0; i < outs; i++) {
16200c8c0f56STakashi Iwai 		struct nid_path *path;
1621352f7f91STakashi Iwai 		hda_nid_t dac;
1622352f7f91STakashi Iwai 		if (dacs[i])
1623352f7f91STakashi Iwai 			continue;
1624352f7f91STakashi Iwai 		dac = get_dac_if_single(codec, pins[i]);
1625352f7f91STakashi Iwai 		if (!dac)
1626352f7f91STakashi Iwai 			continue;
16273ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dac, pins[i],
16283ca529d3STakashi Iwai 					    -spec->mixer_nid);
1629117688a9STakashi Iwai 		if (!path && !i && spec->mixer_nid)
16303ca529d3STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
16310c8c0f56STakashi Iwai 		if (path) {
1632352f7f91STakashi Iwai 			dacs[i] = dac;
1633352f7f91STakashi Iwai 			found = true;
16344e76a883STakashi Iwai 			/* print_nid_path(codec, "output", path); */
1635e1284af7STakashi Iwai 			path->active = true;
1636196c1766STakashi Iwai 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1637352f7f91STakashi Iwai 		}
1638352f7f91STakashi Iwai 	}
1639352f7f91STakashi Iwai 	return found;
1640352f7f91STakashi Iwai }
1641352f7f91STakashi Iwai 
1642e7fdd527STakashi Iwai static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1643e7fdd527STakashi Iwai {
1644e7fdd527STakashi Iwai 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1645e7fdd527STakashi Iwai 		spec->aamix_out_paths[2];
1646e7fdd527STakashi Iwai }
1647e7fdd527STakashi Iwai 
1648c30aa7b2STakashi Iwai /* create a new path including aamix if available, and return its index */
1649c30aa7b2STakashi Iwai static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1650c30aa7b2STakashi Iwai {
16513ca529d3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1652c30aa7b2STakashi Iwai 	struct nid_path *path;
16535ead56f2STakashi Iwai 	hda_nid_t path_dac, dac, pin;
1654c30aa7b2STakashi Iwai 
1655c30aa7b2STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
16563ca529d3STakashi Iwai 	if (!path || !path->depth ||
16573ca529d3STakashi Iwai 	    is_nid_contained(path, spec->mixer_nid))
1658c30aa7b2STakashi Iwai 		return 0;
16595ead56f2STakashi Iwai 	path_dac = path->path[0];
16605ead56f2STakashi Iwai 	dac = spec->private_dac_nids[0];
1661f87498b6STakashi Iwai 	pin = path->path[path->depth - 1];
1662f87498b6STakashi Iwai 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1663f87498b6STakashi Iwai 	if (!path) {
16645ead56f2STakashi Iwai 		if (dac != path_dac)
16655ead56f2STakashi Iwai 			dac = path_dac;
1666f87498b6STakashi Iwai 		else if (spec->multiout.hp_out_nid[0])
1667f87498b6STakashi Iwai 			dac = spec->multiout.hp_out_nid[0];
1668f87498b6STakashi Iwai 		else if (spec->multiout.extra_out_nid[0])
1669f87498b6STakashi Iwai 			dac = spec->multiout.extra_out_nid[0];
16705ead56f2STakashi Iwai 		else
16715ead56f2STakashi Iwai 			dac = 0;
1672f87498b6STakashi Iwai 		if (dac)
1673f87498b6STakashi Iwai 			path = snd_hda_add_new_path(codec, dac, pin,
16743ca529d3STakashi Iwai 						    spec->mixer_nid);
1675f87498b6STakashi Iwai 	}
1676c30aa7b2STakashi Iwai 	if (!path)
1677c30aa7b2STakashi Iwai 		return 0;
16784e76a883STakashi Iwai 	/* print_nid_path(codec, "output-aamix", path); */
1679c30aa7b2STakashi Iwai 	path->active = false; /* unused as default */
16806b275b14STakashi Iwai 	path->pin_fixed = true; /* static route */
1681c30aa7b2STakashi Iwai 	return snd_hda_get_path_idx(codec, path);
1682c30aa7b2STakashi Iwai }
1683c30aa7b2STakashi Iwai 
168455a63d4dSTakashi Iwai /* check whether the independent HP is available with the current config */
168555a63d4dSTakashi Iwai static bool indep_hp_possible(struct hda_codec *codec)
168655a63d4dSTakashi Iwai {
168755a63d4dSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
168855a63d4dSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
168955a63d4dSTakashi Iwai 	struct nid_path *path;
169055a63d4dSTakashi Iwai 	int i, idx;
169155a63d4dSTakashi Iwai 
169255a63d4dSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
169355a63d4dSTakashi Iwai 		idx = spec->out_paths[0];
169455a63d4dSTakashi Iwai 	else
169555a63d4dSTakashi Iwai 		idx = spec->hp_paths[0];
169655a63d4dSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
169755a63d4dSTakashi Iwai 	if (!path)
169855a63d4dSTakashi Iwai 		return false;
169955a63d4dSTakashi Iwai 
170055a63d4dSTakashi Iwai 	/* assume no path conflicts unless aamix is involved */
170155a63d4dSTakashi Iwai 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
170255a63d4dSTakashi Iwai 		return true;
170355a63d4dSTakashi Iwai 
170455a63d4dSTakashi Iwai 	/* check whether output paths contain aamix */
170555a63d4dSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
170655a63d4dSTakashi Iwai 		if (spec->out_paths[i] == idx)
170755a63d4dSTakashi Iwai 			break;
170855a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
170955a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
171055a63d4dSTakashi Iwai 			return false;
171155a63d4dSTakashi Iwai 	}
171255a63d4dSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++) {
171355a63d4dSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
171455a63d4dSTakashi Iwai 		if (path && is_nid_contained(path, spec->mixer_nid))
171555a63d4dSTakashi Iwai 			return false;
171655a63d4dSTakashi Iwai 	}
171755a63d4dSTakashi Iwai 
171855a63d4dSTakashi Iwai 	return true;
171955a63d4dSTakashi Iwai }
172055a63d4dSTakashi Iwai 
1721a07a949bSTakashi Iwai /* fill the empty entries in the dac array for speaker/hp with the
1722a07a949bSTakashi Iwai  * shared dac pointed by the paths
1723a07a949bSTakashi Iwai  */
1724a07a949bSTakashi Iwai static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1725a07a949bSTakashi Iwai 			       hda_nid_t *dacs, int *path_idx)
1726a07a949bSTakashi Iwai {
1727a07a949bSTakashi Iwai 	struct nid_path *path;
1728a07a949bSTakashi Iwai 	int i;
1729a07a949bSTakashi Iwai 
1730a07a949bSTakashi Iwai 	for (i = 0; i < num_outs; i++) {
1731a07a949bSTakashi Iwai 		if (dacs[i])
1732a07a949bSTakashi Iwai 			continue;
1733a07a949bSTakashi Iwai 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1734a07a949bSTakashi Iwai 		if (!path)
1735a07a949bSTakashi Iwai 			continue;
1736a07a949bSTakashi Iwai 		dacs[i] = path->path[0];
1737a07a949bSTakashi Iwai 	}
1738a07a949bSTakashi Iwai }
1739a07a949bSTakashi Iwai 
1740352f7f91STakashi Iwai /* fill in the dac_nids table from the parsed pin configuration */
1741352f7f91STakashi Iwai static int fill_and_eval_dacs(struct hda_codec *codec,
1742352f7f91STakashi Iwai 			      bool fill_hardwired,
1743352f7f91STakashi Iwai 			      bool fill_mio_first)
1744352f7f91STakashi Iwai {
1745352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1746352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1747352f7f91STakashi Iwai 	int i, err, badness;
1748352f7f91STakashi Iwai 
1749352f7f91STakashi Iwai 	/* set num_dacs once to full for look_for_dac() */
1750352f7f91STakashi Iwai 	spec->multiout.num_dacs = cfg->line_outs;
1751352f7f91STakashi Iwai 	spec->multiout.dac_nids = spec->private_dac_nids;
1752352f7f91STakashi Iwai 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1753352f7f91STakashi Iwai 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1754352f7f91STakashi Iwai 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1755352f7f91STakashi Iwai 	spec->multi_ios = 0;
1756352f7f91STakashi Iwai 	snd_array_free(&spec->paths);
1757cd5be3f9STakashi Iwai 
1758cd5be3f9STakashi Iwai 	/* clear path indices */
1759cd5be3f9STakashi Iwai 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1760cd5be3f9STakashi Iwai 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1761cd5be3f9STakashi Iwai 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1762cd5be3f9STakashi Iwai 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1763cd5be3f9STakashi Iwai 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1764c697b716STakashi Iwai 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1765cd5be3f9STakashi Iwai 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1766cd5be3f9STakashi Iwai 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1767cd5be3f9STakashi Iwai 
1768352f7f91STakashi Iwai 	badness = 0;
1769352f7f91STakashi Iwai 
1770352f7f91STakashi Iwai 	/* fill hard-wired DACs first */
1771352f7f91STakashi Iwai 	if (fill_hardwired) {
1772352f7f91STakashi Iwai 		bool mapped;
1773352f7f91STakashi Iwai 		do {
1774352f7f91STakashi Iwai 			mapped = map_singles(codec, cfg->line_outs,
1775352f7f91STakashi Iwai 					     cfg->line_out_pins,
1776196c1766STakashi Iwai 					     spec->private_dac_nids,
1777196c1766STakashi Iwai 					     spec->out_paths);
1778352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->hp_outs,
1779352f7f91STakashi Iwai 					      cfg->hp_pins,
1780196c1766STakashi Iwai 					      spec->multiout.hp_out_nid,
1781196c1766STakashi Iwai 					      spec->hp_paths);
1782352f7f91STakashi Iwai 			mapped |= map_singles(codec, cfg->speaker_outs,
1783352f7f91STakashi Iwai 					      cfg->speaker_pins,
1784196c1766STakashi Iwai 					      spec->multiout.extra_out_nid,
1785196c1766STakashi Iwai 					      spec->speaker_paths);
1786da96fb5bSTakashi Iwai 			if (!spec->no_multi_io &&
1787da96fb5bSTakashi Iwai 			    fill_mio_first && cfg->line_outs == 1 &&
1788352f7f91STakashi Iwai 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1789e22aab7dSTakashi Iwai 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1790352f7f91STakashi Iwai 				if (!err)
1791352f7f91STakashi Iwai 					mapped = true;
1792352f7f91STakashi Iwai 			}
1793352f7f91STakashi Iwai 		} while (mapped);
1794352f7f91STakashi Iwai 	}
1795352f7f91STakashi Iwai 
1796352f7f91STakashi Iwai 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1797196c1766STakashi Iwai 				   spec->private_dac_nids, spec->out_paths,
179898bd1115STakashi Iwai 				   spec->main_out_badness);
1799352f7f91STakashi Iwai 
1800da96fb5bSTakashi Iwai 	if (!spec->no_multi_io && fill_mio_first &&
1801352f7f91STakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1802352f7f91STakashi Iwai 		/* try to fill multi-io first */
1803e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1804352f7f91STakashi Iwai 		if (err < 0)
1805352f7f91STakashi Iwai 			return err;
1806352f7f91STakashi Iwai 		/* we don't count badness at this stage yet */
1807352f7f91STakashi Iwai 	}
1808352f7f91STakashi Iwai 
1809352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1810352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1811352f7f91STakashi Iwai 				      spec->multiout.hp_out_nid,
1812196c1766STakashi Iwai 				      spec->hp_paths,
181398bd1115STakashi Iwai 				      spec->extra_out_badness);
1814352f7f91STakashi Iwai 		if (err < 0)
1815352f7f91STakashi Iwai 			return err;
1816352f7f91STakashi Iwai 		badness += err;
1817352f7f91STakashi Iwai 	}
1818352f7f91STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1819352f7f91STakashi Iwai 		err = try_assign_dacs(codec, cfg->speaker_outs,
1820352f7f91STakashi Iwai 				      cfg->speaker_pins,
1821352f7f91STakashi Iwai 				      spec->multiout.extra_out_nid,
1822196c1766STakashi Iwai 				      spec->speaker_paths,
182398bd1115STakashi Iwai 				      spec->extra_out_badness);
1824352f7f91STakashi Iwai 		if (err < 0)
1825352f7f91STakashi Iwai 			return err;
1826352f7f91STakashi Iwai 		badness += err;
1827352f7f91STakashi Iwai 	}
1828da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1829da96fb5bSTakashi Iwai 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1830e22aab7dSTakashi Iwai 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1831352f7f91STakashi Iwai 		if (err < 0)
1832352f7f91STakashi Iwai 			return err;
1833352f7f91STakashi Iwai 		badness += err;
1834352f7f91STakashi Iwai 	}
1835e22aab7dSTakashi Iwai 
1836c30aa7b2STakashi Iwai 	if (spec->mixer_nid) {
1837c30aa7b2STakashi Iwai 		spec->aamix_out_paths[0] =
1838c30aa7b2STakashi Iwai 			check_aamix_out_path(codec, spec->out_paths[0]);
1839c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1840c30aa7b2STakashi Iwai 			spec->aamix_out_paths[1] =
1841c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->hp_paths[0]);
1842c30aa7b2STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1843c30aa7b2STakashi Iwai 			spec->aamix_out_paths[2] =
1844c30aa7b2STakashi Iwai 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1845c30aa7b2STakashi Iwai 	}
1846c30aa7b2STakashi Iwai 
1847da96fb5bSTakashi Iwai 	if (!spec->no_multi_io &&
1848da96fb5bSTakashi Iwai 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1849e22aab7dSTakashi Iwai 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1850e22aab7dSTakashi Iwai 			spec->multi_ios = 1; /* give badness */
1851352f7f91STakashi Iwai 
1852a07a949bSTakashi Iwai 	/* re-count num_dacs and squash invalid entries */
1853a07a949bSTakashi Iwai 	spec->multiout.num_dacs = 0;
1854a07a949bSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++) {
1855a07a949bSTakashi Iwai 		if (spec->private_dac_nids[i])
1856a07a949bSTakashi Iwai 			spec->multiout.num_dacs++;
1857a07a949bSTakashi Iwai 		else {
1858a07a949bSTakashi Iwai 			memmove(spec->private_dac_nids + i,
1859a07a949bSTakashi Iwai 				spec->private_dac_nids + i + 1,
1860a07a949bSTakashi Iwai 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1861a07a949bSTakashi Iwai 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1862a07a949bSTakashi Iwai 		}
1863a07a949bSTakashi Iwai 	}
1864a07a949bSTakashi Iwai 
1865a07a949bSTakashi Iwai 	spec->ext_channel_count = spec->min_channel_count =
1866c0f3b216SDavid Henningsson 		spec->multiout.num_dacs * 2;
1867a07a949bSTakashi Iwai 
1868352f7f91STakashi Iwai 	if (spec->multi_ios == 2) {
1869352f7f91STakashi Iwai 		for (i = 0; i < 2; i++)
1870352f7f91STakashi Iwai 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1871352f7f91STakashi Iwai 				spec->multi_io[i].dac;
1872352f7f91STakashi Iwai 	} else if (spec->multi_ios) {
1873352f7f91STakashi Iwai 		spec->multi_ios = 0;
1874352f7f91STakashi Iwai 		badness += BAD_MULTI_IO;
1875352f7f91STakashi Iwai 	}
1876352f7f91STakashi Iwai 
187755a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
187855a63d4dSTakashi Iwai 		badness += BAD_NO_INDEP_HP;
187955a63d4dSTakashi Iwai 
1880a07a949bSTakashi Iwai 	/* re-fill the shared DAC for speaker / headphone */
1881a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1882a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->hp_outs,
1883a07a949bSTakashi Iwai 				   spec->multiout.hp_out_nid,
1884a07a949bSTakashi Iwai 				   spec->hp_paths);
1885a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1886a07a949bSTakashi Iwai 		refill_shared_dacs(codec, cfg->speaker_outs,
1887a07a949bSTakashi Iwai 				   spec->multiout.extra_out_nid,
1888a07a949bSTakashi Iwai 				   spec->speaker_paths);
1889a07a949bSTakashi Iwai 
1890352f7f91STakashi Iwai 	return badness;
1891352f7f91STakashi Iwai }
1892352f7f91STakashi Iwai 
1893352f7f91STakashi Iwai #define DEBUG_BADNESS
1894352f7f91STakashi Iwai 
1895352f7f91STakashi Iwai #ifdef DEBUG_BADNESS
1896d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1897d82353e5SJoe Perches 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1898352f7f91STakashi Iwai #else
1899d82353e5SJoe Perches #define debug_badness(fmt, ...)						\
1900d82353e5SJoe Perches 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1901352f7f91STakashi Iwai #endif
1902352f7f91STakashi Iwai 
1903a769409cSTakashi Iwai #ifdef DEBUG_BADNESS
1904a769409cSTakashi Iwai static inline void print_nid_path_idx(struct hda_codec *codec,
1905a769409cSTakashi Iwai 				      const char *pfx, int idx)
1906352f7f91STakashi Iwai {
1907a769409cSTakashi Iwai 	struct nid_path *path;
1908a769409cSTakashi Iwai 
1909a769409cSTakashi Iwai 	path = snd_hda_get_path_from_idx(codec, idx);
1910a769409cSTakashi Iwai 	if (path)
19114e76a883STakashi Iwai 		print_nid_path(codec, pfx, path);
1912a769409cSTakashi Iwai }
1913a769409cSTakashi Iwai 
1914a769409cSTakashi Iwai static void debug_show_configs(struct hda_codec *codec,
1915a769409cSTakashi Iwai 			       struct auto_pin_cfg *cfg)
1916a769409cSTakashi Iwai {
1917a769409cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1918a769409cSTakashi Iwai 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1919a769409cSTakashi Iwai 	int i;
1920a769409cSTakashi Iwai 
1921a769409cSTakashi Iwai 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1922352f7f91STakashi Iwai 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1923708122e8STakashi Iwai 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1924352f7f91STakashi Iwai 		      spec->multiout.dac_nids[0],
1925352f7f91STakashi Iwai 		      spec->multiout.dac_nids[1],
1926352f7f91STakashi Iwai 		      spec->multiout.dac_nids[2],
1927a769409cSTakashi Iwai 		      spec->multiout.dac_nids[3],
1928a769409cSTakashi Iwai 		      lo_type[cfg->line_out_type]);
1929a769409cSTakashi Iwai 	for (i = 0; i < cfg->line_outs; i++)
1930a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1931352f7f91STakashi Iwai 	if (spec->multi_ios > 0)
1932352f7f91STakashi Iwai 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1933352f7f91STakashi Iwai 			      spec->multi_ios,
1934352f7f91STakashi Iwai 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1935352f7f91STakashi Iwai 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1936a769409cSTakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
1937a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mio",
1938a769409cSTakashi Iwai 				   spec->out_paths[cfg->line_outs + i]);
1939a769409cSTakashi Iwai 	if (cfg->hp_outs)
1940352f7f91STakashi Iwai 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1941352f7f91STakashi Iwai 		      cfg->hp_pins[0], cfg->hp_pins[1],
1942708122e8STakashi Iwai 		      cfg->hp_pins[2], cfg->hp_pins[3],
1943352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[0],
1944352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[1],
1945352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[2],
1946352f7f91STakashi Iwai 		      spec->multiout.hp_out_nid[3]);
1947a769409cSTakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++)
1948a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1949a769409cSTakashi Iwai 	if (cfg->speaker_outs)
1950352f7f91STakashi Iwai 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1951352f7f91STakashi Iwai 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1952352f7f91STakashi Iwai 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1953352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[0],
1954352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[1],
1955352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[2],
1956352f7f91STakashi Iwai 		      spec->multiout.extra_out_nid[3]);
1957a769409cSTakashi Iwai 	for (i = 0; i < cfg->speaker_outs; i++)
1958a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1959a769409cSTakashi Iwai 	for (i = 0; i < 3; i++)
1960a769409cSTakashi Iwai 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1961352f7f91STakashi Iwai }
1962a769409cSTakashi Iwai #else
1963a769409cSTakashi Iwai #define debug_show_configs(codec, cfg) /* NOP */
1964a769409cSTakashi Iwai #endif
1965352f7f91STakashi Iwai 
1966352f7f91STakashi Iwai /* find all available DACs of the codec */
1967352f7f91STakashi Iwai static void fill_all_dac_nids(struct hda_codec *codec)
1968352f7f91STakashi Iwai {
1969352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
19707639a06cSTakashi Iwai 	hda_nid_t nid;
1971352f7f91STakashi Iwai 
1972352f7f91STakashi Iwai 	spec->num_all_dacs = 0;
1973352f7f91STakashi Iwai 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
19747639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
1975352f7f91STakashi Iwai 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1976352f7f91STakashi Iwai 			continue;
1977352f7f91STakashi Iwai 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
19784e76a883STakashi Iwai 			codec_err(codec, "Too many DACs!\n");
1979352f7f91STakashi Iwai 			break;
1980352f7f91STakashi Iwai 		}
1981352f7f91STakashi Iwai 		spec->all_dacs[spec->num_all_dacs++] = nid;
1982352f7f91STakashi Iwai 	}
1983352f7f91STakashi Iwai }
1984352f7f91STakashi Iwai 
1985352f7f91STakashi Iwai static int parse_output_paths(struct hda_codec *codec)
1986352f7f91STakashi Iwai {
1987352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
1988352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
1989352f7f91STakashi Iwai 	struct auto_pin_cfg *best_cfg;
19909314a581STakashi Iwai 	unsigned int val;
1991352f7f91STakashi Iwai 	int best_badness = INT_MAX;
1992352f7f91STakashi Iwai 	int badness;
1993352f7f91STakashi Iwai 	bool fill_hardwired = true, fill_mio_first = true;
1994352f7f91STakashi Iwai 	bool best_wired = true, best_mio = true;
1995352f7f91STakashi Iwai 	bool hp_spk_swapped = false;
1996352f7f91STakashi Iwai 
1997352f7f91STakashi Iwai 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1998352f7f91STakashi Iwai 	if (!best_cfg)
1999352f7f91STakashi Iwai 		return -ENOMEM;
2000352f7f91STakashi Iwai 	*best_cfg = *cfg;
2001352f7f91STakashi Iwai 
2002352f7f91STakashi Iwai 	for (;;) {
2003352f7f91STakashi Iwai 		badness = fill_and_eval_dacs(codec, fill_hardwired,
2004352f7f91STakashi Iwai 					     fill_mio_first);
2005352f7f91STakashi Iwai 		if (badness < 0) {
2006352f7f91STakashi Iwai 			kfree(best_cfg);
2007352f7f91STakashi Iwai 			return badness;
2008352f7f91STakashi Iwai 		}
2009352f7f91STakashi Iwai 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
2010352f7f91STakashi Iwai 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
2011352f7f91STakashi Iwai 			      badness);
2012a769409cSTakashi Iwai 		debug_show_configs(codec, cfg);
2013352f7f91STakashi Iwai 		if (badness < best_badness) {
2014352f7f91STakashi Iwai 			best_badness = badness;
2015352f7f91STakashi Iwai 			*best_cfg = *cfg;
2016352f7f91STakashi Iwai 			best_wired = fill_hardwired;
2017352f7f91STakashi Iwai 			best_mio = fill_mio_first;
2018352f7f91STakashi Iwai 		}
2019352f7f91STakashi Iwai 		if (!badness)
2020352f7f91STakashi Iwai 			break;
2021352f7f91STakashi Iwai 		fill_mio_first = !fill_mio_first;
2022352f7f91STakashi Iwai 		if (!fill_mio_first)
2023352f7f91STakashi Iwai 			continue;
2024352f7f91STakashi Iwai 		fill_hardwired = !fill_hardwired;
2025352f7f91STakashi Iwai 		if (!fill_hardwired)
2026352f7f91STakashi Iwai 			continue;
2027352f7f91STakashi Iwai 		if (hp_spk_swapped)
2028352f7f91STakashi Iwai 			break;
2029352f7f91STakashi Iwai 		hp_spk_swapped = true;
2030352f7f91STakashi Iwai 		if (cfg->speaker_outs > 0 &&
2031352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2032352f7f91STakashi Iwai 			cfg->hp_outs = cfg->line_outs;
2033352f7f91STakashi Iwai 			memcpy(cfg->hp_pins, cfg->line_out_pins,
2034352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2035352f7f91STakashi Iwai 			cfg->line_outs = cfg->speaker_outs;
2036352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
2037352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2038352f7f91STakashi Iwai 			cfg->speaker_outs = 0;
2039352f7f91STakashi Iwai 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
2040352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
2041352f7f91STakashi Iwai 			fill_hardwired = true;
2042352f7f91STakashi Iwai 			continue;
2043352f7f91STakashi Iwai 		}
2044352f7f91STakashi Iwai 		if (cfg->hp_outs > 0 &&
2045352f7f91STakashi Iwai 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2046352f7f91STakashi Iwai 			cfg->speaker_outs = cfg->line_outs;
2047352f7f91STakashi Iwai 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
2048352f7f91STakashi Iwai 			       sizeof(cfg->speaker_pins));
2049352f7f91STakashi Iwai 			cfg->line_outs = cfg->hp_outs;
2050352f7f91STakashi Iwai 			memcpy(cfg->line_out_pins, cfg->hp_pins,
2051352f7f91STakashi Iwai 			       sizeof(cfg->hp_pins));
2052352f7f91STakashi Iwai 			cfg->hp_outs = 0;
2053352f7f91STakashi Iwai 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2054352f7f91STakashi Iwai 			cfg->line_out_type = AUTO_PIN_HP_OUT;
2055352f7f91STakashi Iwai 			fill_hardwired = true;
2056352f7f91STakashi Iwai 			continue;
2057352f7f91STakashi Iwai 		}
2058352f7f91STakashi Iwai 		break;
2059352f7f91STakashi Iwai 	}
2060352f7f91STakashi Iwai 
2061352f7f91STakashi Iwai 	if (badness) {
20620c8c0f56STakashi Iwai 		debug_badness("==> restoring best_cfg\n");
2063352f7f91STakashi Iwai 		*cfg = *best_cfg;
2064352f7f91STakashi Iwai 		fill_and_eval_dacs(codec, best_wired, best_mio);
2065352f7f91STakashi Iwai 	}
2066352f7f91STakashi Iwai 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2067352f7f91STakashi Iwai 		      cfg->line_out_type, best_wired, best_mio);
2068a769409cSTakashi Iwai 	debug_show_configs(codec, cfg);
2069352f7f91STakashi Iwai 
2070352f7f91STakashi Iwai 	if (cfg->line_out_pins[0]) {
2071352f7f91STakashi Iwai 		struct nid_path *path;
2072196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2073352f7f91STakashi Iwai 		if (path)
2074352f7f91STakashi Iwai 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2075d89c6c0cSTakashi Iwai 		if (spec->vmaster_nid) {
20767a71bbf3STakashi Iwai 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
20777a71bbf3STakashi Iwai 						HDA_OUTPUT, spec->vmaster_tlv);
2078d89c6c0cSTakashi Iwai 			if (spec->dac_min_mute)
207951cdc8b6STakashi Sakamoto 				spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
2080d89c6c0cSTakashi Iwai 		}
2081352f7f91STakashi Iwai 	}
2082352f7f91STakashi Iwai 
20839314a581STakashi Iwai 	/* set initial pinctl targets */
20849314a581STakashi Iwai 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
20859314a581STakashi Iwai 		val = PIN_HP;
20869314a581STakashi Iwai 	else
20879314a581STakashi Iwai 		val = PIN_OUT;
20889314a581STakashi Iwai 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
20899314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
20909314a581STakashi Iwai 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
20919314a581STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
20929314a581STakashi Iwai 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
20939314a581STakashi Iwai 		set_pin_targets(codec, cfg->speaker_outs,
20949314a581STakashi Iwai 				cfg->speaker_pins, val);
20959314a581STakashi Iwai 	}
20969314a581STakashi Iwai 
209755a63d4dSTakashi Iwai 	/* clear indep_hp flag if not available */
209855a63d4dSTakashi Iwai 	if (spec->indep_hp && !indep_hp_possible(codec))
209955a63d4dSTakashi Iwai 		spec->indep_hp = 0;
210055a63d4dSTakashi Iwai 
2101352f7f91STakashi Iwai 	kfree(best_cfg);
2102352f7f91STakashi Iwai 	return 0;
2103352f7f91STakashi Iwai }
2104352f7f91STakashi Iwai 
2105352f7f91STakashi Iwai /* add playback controls from the parsed DAC table */
2106352f7f91STakashi Iwai static int create_multi_out_ctls(struct hda_codec *codec,
2107352f7f91STakashi Iwai 				 const struct auto_pin_cfg *cfg)
2108352f7f91STakashi Iwai {
2109352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2110352f7f91STakashi Iwai 	int i, err, noutputs;
2111352f7f91STakashi Iwai 
2112352f7f91STakashi Iwai 	noutputs = cfg->line_outs;
2113352f7f91STakashi Iwai 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2114352f7f91STakashi Iwai 		noutputs += spec->multi_ios;
2115352f7f91STakashi Iwai 
2116352f7f91STakashi Iwai 	for (i = 0; i < noutputs; i++) {
2117352f7f91STakashi Iwai 		const char *name;
2118352f7f91STakashi Iwai 		int index;
2119352f7f91STakashi Iwai 		struct nid_path *path;
2120352f7f91STakashi Iwai 
2121196c1766STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2122352f7f91STakashi Iwai 		if (!path)
2123352f7f91STakashi Iwai 			continue;
2124247d85eeSTakashi Iwai 
2125247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2126352f7f91STakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2127352f7f91STakashi Iwai 			/* Center/LFE */
2128352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2129352f7f91STakashi Iwai 			if (err < 0)
2130352f7f91STakashi Iwai 				return err;
2131352f7f91STakashi Iwai 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2132352f7f91STakashi Iwai 			if (err < 0)
2133352f7f91STakashi Iwai 				return err;
2134247d85eeSTakashi Iwai 		} else {
2135247d85eeSTakashi Iwai 			err = add_stereo_vol(codec, name, index, path);
2136247d85eeSTakashi Iwai 			if (err < 0)
2137247d85eeSTakashi Iwai 				return err;
2138247d85eeSTakashi Iwai 		}
2139247d85eeSTakashi Iwai 
2140247d85eeSTakashi Iwai 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2141247d85eeSTakashi Iwai 		if (!name || !strcmp(name, "CLFE")) {
2142352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2143352f7f91STakashi Iwai 			if (err < 0)
2144352f7f91STakashi Iwai 				return err;
2145352f7f91STakashi Iwai 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2146352f7f91STakashi Iwai 			if (err < 0)
2147352f7f91STakashi Iwai 				return err;
2148352f7f91STakashi Iwai 		} else {
2149352f7f91STakashi Iwai 			err = add_stereo_sw(codec, name, index, path);
2150352f7f91STakashi Iwai 			if (err < 0)
2151352f7f91STakashi Iwai 				return err;
2152352f7f91STakashi Iwai 		}
2153352f7f91STakashi Iwai 	}
2154352f7f91STakashi Iwai 	return 0;
2155352f7f91STakashi Iwai }
2156352f7f91STakashi Iwai 
2157c2c80383STakashi Iwai static int create_extra_out(struct hda_codec *codec, int path_idx,
2158196c1766STakashi Iwai 			    const char *pfx, int cidx)
2159352f7f91STakashi Iwai {
2160352f7f91STakashi Iwai 	struct nid_path *path;
2161352f7f91STakashi Iwai 	int err;
2162352f7f91STakashi Iwai 
2163196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
2164352f7f91STakashi Iwai 	if (!path)
2165352f7f91STakashi Iwai 		return 0;
2166352f7f91STakashi Iwai 	err = add_stereo_vol(codec, pfx, cidx, path);
2167352f7f91STakashi Iwai 	if (err < 0)
2168352f7f91STakashi Iwai 		return err;
2169352f7f91STakashi Iwai 	err = add_stereo_sw(codec, pfx, cidx, path);
2170352f7f91STakashi Iwai 	if (err < 0)
2171352f7f91STakashi Iwai 		return err;
2172352f7f91STakashi Iwai 	return 0;
2173352f7f91STakashi Iwai }
2174352f7f91STakashi Iwai 
2175352f7f91STakashi Iwai /* add playback controls for speaker and HP outputs */
2176352f7f91STakashi Iwai static int create_extra_outs(struct hda_codec *codec, int num_pins,
2177196c1766STakashi Iwai 			     const int *paths, const char *pfx)
2178352f7f91STakashi Iwai {
2179c2c80383STakashi Iwai 	int i;
2180352f7f91STakashi Iwai 
2181352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2182c2c80383STakashi Iwai 		const char *name;
2183975cc02aSTakashi Iwai 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2184c2c80383STakashi Iwai 		int err, idx = 0;
2185c2c80383STakashi Iwai 
2186c2c80383STakashi Iwai 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2187c2c80383STakashi Iwai 			name = "Bass Speaker";
2188c2c80383STakashi Iwai 		else if (num_pins >= 3) {
2189c2c80383STakashi Iwai 			snprintf(tmp, sizeof(tmp), "%s %s",
2190352f7f91STakashi Iwai 				 pfx, channel_name[i]);
2191c2c80383STakashi Iwai 			name = tmp;
2192352f7f91STakashi Iwai 		} else {
2193c2c80383STakashi Iwai 			name = pfx;
2194c2c80383STakashi Iwai 			idx = i;
2195352f7f91STakashi Iwai 		}
2196c2c80383STakashi Iwai 		err = create_extra_out(codec, paths[i], name, idx);
2197352f7f91STakashi Iwai 		if (err < 0)
2198352f7f91STakashi Iwai 			return err;
2199352f7f91STakashi Iwai 	}
2200352f7f91STakashi Iwai 	return 0;
2201352f7f91STakashi Iwai }
2202352f7f91STakashi Iwai 
2203352f7f91STakashi Iwai static int create_hp_out_ctls(struct hda_codec *codec)
2204352f7f91STakashi Iwai {
2205352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2206352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2207196c1766STakashi Iwai 				 spec->hp_paths,
2208352f7f91STakashi Iwai 				 "Headphone");
2209352f7f91STakashi Iwai }
2210352f7f91STakashi Iwai 
2211352f7f91STakashi Iwai static int create_speaker_out_ctls(struct hda_codec *codec)
2212352f7f91STakashi Iwai {
2213352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2214352f7f91STakashi Iwai 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2215196c1766STakashi Iwai 				 spec->speaker_paths,
2216352f7f91STakashi Iwai 				 "Speaker");
2217352f7f91STakashi Iwai }
2218352f7f91STakashi Iwai 
2219352f7f91STakashi Iwai /*
222038cf6f1aSTakashi Iwai  * independent HP controls
222138cf6f1aSTakashi Iwai  */
222238cf6f1aSTakashi Iwai 
22231a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
22241a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack);
222538cf6f1aSTakashi Iwai static int indep_hp_info(struct snd_kcontrol *kcontrol,
222638cf6f1aSTakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
222738cf6f1aSTakashi Iwai {
222838cf6f1aSTakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
222938cf6f1aSTakashi Iwai }
223038cf6f1aSTakashi Iwai 
223138cf6f1aSTakashi Iwai static int indep_hp_get(struct snd_kcontrol *kcontrol,
223238cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
223338cf6f1aSTakashi Iwai {
223438cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
223538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
223638cf6f1aSTakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
223738cf6f1aSTakashi Iwai 	return 0;
223838cf6f1aSTakashi Iwai }
223938cf6f1aSTakashi Iwai 
2240a1e908edSTakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2241a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2242a1e908edSTakashi Iwai 			       int out_type);
2243a1e908edSTakashi Iwai 
224438cf6f1aSTakashi Iwai static int indep_hp_put(struct snd_kcontrol *kcontrol,
224538cf6f1aSTakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
224638cf6f1aSTakashi Iwai {
224738cf6f1aSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
224838cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
224938cf6f1aSTakashi Iwai 	unsigned int select = ucontrol->value.enumerated.item[0];
225038cf6f1aSTakashi Iwai 	int ret = 0;
225138cf6f1aSTakashi Iwai 
225238cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
225338cf6f1aSTakashi Iwai 	if (spec->active_streams) {
225438cf6f1aSTakashi Iwai 		ret = -EBUSY;
225538cf6f1aSTakashi Iwai 		goto unlock;
225638cf6f1aSTakashi Iwai 	}
225738cf6f1aSTakashi Iwai 
225838cf6f1aSTakashi Iwai 	if (spec->indep_hp_enabled != select) {
2259a1e908edSTakashi Iwai 		hda_nid_t *dacp;
2260a1e908edSTakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2261a1e908edSTakashi Iwai 			dacp = &spec->private_dac_nids[0];
2262a1e908edSTakashi Iwai 		else
2263a1e908edSTakashi Iwai 			dacp = &spec->multiout.hp_out_nid[0];
2264a1e908edSTakashi Iwai 
2265a1e908edSTakashi Iwai 		/* update HP aamix paths in case it conflicts with indep HP */
2266a1e908edSTakashi Iwai 		if (spec->have_aamix_ctl) {
2267a1e908edSTakashi Iwai 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2268a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2269a1e908edSTakashi Iwai 						   spec->out_paths[0],
2270a1e908edSTakashi Iwai 						   spec->aamix_out_paths[0],
2271a1e908edSTakashi Iwai 						   spec->autocfg.line_out_type);
2272a1e908edSTakashi Iwai 			else
2273a1e908edSTakashi Iwai 				update_aamix_paths(codec, spec->aamix_mode,
2274a1e908edSTakashi Iwai 						   spec->hp_paths[0],
2275a1e908edSTakashi Iwai 						   spec->aamix_out_paths[1],
2276a1e908edSTakashi Iwai 						   AUTO_PIN_HP_OUT);
2277a1e908edSTakashi Iwai 		}
2278a1e908edSTakashi Iwai 
227938cf6f1aSTakashi Iwai 		spec->indep_hp_enabled = select;
228038cf6f1aSTakashi Iwai 		if (spec->indep_hp_enabled)
2281a1e908edSTakashi Iwai 			*dacp = 0;
228238cf6f1aSTakashi Iwai 		else
2283a1e908edSTakashi Iwai 			*dacp = spec->alt_dac_nid;
228492603c59STakashi Iwai 
2285963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
228638cf6f1aSTakashi Iwai 		ret = 1;
228738cf6f1aSTakashi Iwai 	}
228838cf6f1aSTakashi Iwai  unlock:
228938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
229038cf6f1aSTakashi Iwai 	return ret;
229138cf6f1aSTakashi Iwai }
229238cf6f1aSTakashi Iwai 
229338cf6f1aSTakashi Iwai static const struct snd_kcontrol_new indep_hp_ctl = {
229438cf6f1aSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
229538cf6f1aSTakashi Iwai 	.name = "Independent HP",
229638cf6f1aSTakashi Iwai 	.info = indep_hp_info,
229738cf6f1aSTakashi Iwai 	.get = indep_hp_get,
229838cf6f1aSTakashi Iwai 	.put = indep_hp_put,
229938cf6f1aSTakashi Iwai };
230038cf6f1aSTakashi Iwai 
230138cf6f1aSTakashi Iwai 
230238cf6f1aSTakashi Iwai static int create_indep_hp_ctls(struct hda_codec *codec)
230338cf6f1aSTakashi Iwai {
230438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2305a1e908edSTakashi Iwai 	hda_nid_t dac;
230638cf6f1aSTakashi Iwai 
230738cf6f1aSTakashi Iwai 	if (!spec->indep_hp)
230838cf6f1aSTakashi Iwai 		return 0;
2309a1e908edSTakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2310a1e908edSTakashi Iwai 		dac = spec->multiout.dac_nids[0];
2311a1e908edSTakashi Iwai 	else
2312a1e908edSTakashi Iwai 		dac = spec->multiout.hp_out_nid[0];
2313a1e908edSTakashi Iwai 	if (!dac) {
231438cf6f1aSTakashi Iwai 		spec->indep_hp = 0;
231538cf6f1aSTakashi Iwai 		return 0;
231638cf6f1aSTakashi Iwai 	}
231738cf6f1aSTakashi Iwai 
231838cf6f1aSTakashi Iwai 	spec->indep_hp_enabled = false;
2319a1e908edSTakashi Iwai 	spec->alt_dac_nid = dac;
232038cf6f1aSTakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
232138cf6f1aSTakashi Iwai 		return -ENOMEM;
232238cf6f1aSTakashi Iwai 	return 0;
232338cf6f1aSTakashi Iwai }
232438cf6f1aSTakashi Iwai 
232538cf6f1aSTakashi Iwai /*
2326352f7f91STakashi Iwai  * channel mode enum control
2327352f7f91STakashi Iwai  */
2328352f7f91STakashi Iwai 
2329352f7f91STakashi Iwai static int ch_mode_info(struct snd_kcontrol *kcontrol,
2330352f7f91STakashi Iwai 			struct snd_ctl_elem_info *uinfo)
2331352f7f91STakashi Iwai {
2332352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2333352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2334a07a949bSTakashi Iwai 	int chs;
2335352f7f91STakashi Iwai 
2336352f7f91STakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2337352f7f91STakashi Iwai 	uinfo->count = 1;
2338352f7f91STakashi Iwai 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2339352f7f91STakashi Iwai 	if (uinfo->value.enumerated.item > spec->multi_ios)
2340352f7f91STakashi Iwai 		uinfo->value.enumerated.item = spec->multi_ios;
2341a07a949bSTakashi Iwai 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2342a07a949bSTakashi Iwai 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2343352f7f91STakashi Iwai 	return 0;
2344352f7f91STakashi Iwai }
2345352f7f91STakashi Iwai 
2346352f7f91STakashi Iwai static int ch_mode_get(struct snd_kcontrol *kcontrol,
2347352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2348352f7f91STakashi Iwai {
2349352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2350352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2351a07a949bSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
2352a07a949bSTakashi Iwai 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2353352f7f91STakashi Iwai 	return 0;
2354352f7f91STakashi Iwai }
2355352f7f91STakashi Iwai 
2356196c1766STakashi Iwai static inline struct nid_path *
2357196c1766STakashi Iwai get_multiio_path(struct hda_codec *codec, int idx)
2358196c1766STakashi Iwai {
2359196c1766STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2360196c1766STakashi Iwai 	return snd_hda_get_path_from_idx(codec,
2361196c1766STakashi Iwai 		spec->out_paths[spec->autocfg.line_outs + idx]);
2362196c1766STakashi Iwai }
2363196c1766STakashi Iwai 
2364a5cc2509STakashi Iwai static void update_automute_all(struct hda_codec *codec);
2365a5cc2509STakashi Iwai 
236665033cc8STakashi Iwai /* Default value to be passed as aamix argument for snd_hda_activate_path();
236765033cc8STakashi Iwai  * used for output paths
236865033cc8STakashi Iwai  */
236965033cc8STakashi Iwai static bool aamix_default(struct hda_gen_spec *spec)
237065033cc8STakashi Iwai {
237165033cc8STakashi Iwai 	return !spec->have_aamix_ctl || spec->aamix_mode;
237265033cc8STakashi Iwai }
237365033cc8STakashi Iwai 
2374352f7f91STakashi Iwai static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2375352f7f91STakashi Iwai {
2376352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2377352f7f91STakashi Iwai 	hda_nid_t nid = spec->multi_io[idx].pin;
2378352f7f91STakashi Iwai 	struct nid_path *path;
2379352f7f91STakashi Iwai 
2380196c1766STakashi Iwai 	path = get_multiio_path(codec, idx);
2381352f7f91STakashi Iwai 	if (!path)
2382352f7f91STakashi Iwai 		return -EINVAL;
2383352f7f91STakashi Iwai 
2384352f7f91STakashi Iwai 	if (path->active == output)
2385352f7f91STakashi Iwai 		return 0;
2386352f7f91STakashi Iwai 
2387352f7f91STakashi Iwai 	if (output) {
23882c12c30dSTakashi Iwai 		set_pin_target(codec, nid, PIN_OUT, true);
238965033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2390d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, true);
2391352f7f91STakashi Iwai 	} else {
2392d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, false);
239365033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
23942c12c30dSTakashi Iwai 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
239555196fffSTakashi Iwai 		path_power_down_sync(codec, path);
2396352f7f91STakashi Iwai 	}
2397a365fed9STakashi Iwai 
2398a365fed9STakashi Iwai 	/* update jack retasking in case it modifies any of them */
2399a5cc2509STakashi Iwai 	update_automute_all(codec);
2400a365fed9STakashi Iwai 
2401352f7f91STakashi Iwai 	return 0;
2402352f7f91STakashi Iwai }
2403352f7f91STakashi Iwai 
2404352f7f91STakashi Iwai static int ch_mode_put(struct snd_kcontrol *kcontrol,
2405352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
2406352f7f91STakashi Iwai {
2407352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2408352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2409352f7f91STakashi Iwai 	int i, ch;
2410352f7f91STakashi Iwai 
2411352f7f91STakashi Iwai 	ch = ucontrol->value.enumerated.item[0];
2412352f7f91STakashi Iwai 	if (ch < 0 || ch > spec->multi_ios)
2413352f7f91STakashi Iwai 		return -EINVAL;
2414a07a949bSTakashi Iwai 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2415352f7f91STakashi Iwai 		return 0;
2416a07a949bSTakashi Iwai 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2417352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++)
2418352f7f91STakashi Iwai 		set_multi_io(codec, i, i < ch);
2419352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
2420352f7f91STakashi Iwai 					  spec->const_channel_count);
2421352f7f91STakashi Iwai 	if (spec->need_dac_fix)
2422352f7f91STakashi Iwai 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2423352f7f91STakashi Iwai 	return 1;
2424352f7f91STakashi Iwai }
2425352f7f91STakashi Iwai 
2426352f7f91STakashi Iwai static const struct snd_kcontrol_new channel_mode_enum = {
2427352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2428352f7f91STakashi Iwai 	.name = "Channel Mode",
2429352f7f91STakashi Iwai 	.info = ch_mode_info,
2430352f7f91STakashi Iwai 	.get = ch_mode_get,
2431352f7f91STakashi Iwai 	.put = ch_mode_put,
2432352f7f91STakashi Iwai };
2433352f7f91STakashi Iwai 
2434352f7f91STakashi Iwai static int create_multi_channel_mode(struct hda_codec *codec)
2435352f7f91STakashi Iwai {
2436352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2437352f7f91STakashi Iwai 
2438352f7f91STakashi Iwai 	if (spec->multi_ios > 0) {
243912c93df6STakashi Iwai 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2440352f7f91STakashi Iwai 			return -ENOMEM;
2441352f7f91STakashi Iwai 	}
2442352f7f91STakashi Iwai 	return 0;
2443352f7f91STakashi Iwai }
2444352f7f91STakashi Iwai 
2445352f7f91STakashi Iwai /*
2446c30aa7b2STakashi Iwai  * aamix loopback enable/disable switch
2447c30aa7b2STakashi Iwai  */
2448c30aa7b2STakashi Iwai 
2449c30aa7b2STakashi Iwai #define loopback_mixing_info	indep_hp_info
2450c30aa7b2STakashi Iwai 
2451c30aa7b2STakashi Iwai static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2452c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2453c30aa7b2STakashi Iwai {
2454c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2455c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2456c30aa7b2STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2457c30aa7b2STakashi Iwai 	return 0;
2458c30aa7b2STakashi Iwai }
2459c30aa7b2STakashi Iwai 
2460c30aa7b2STakashi Iwai static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2461a1e908edSTakashi Iwai 			       int nomix_path_idx, int mix_path_idx,
2462a1e908edSTakashi Iwai 			       int out_type)
2463c30aa7b2STakashi Iwai {
2464a1e908edSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2465c30aa7b2STakashi Iwai 	struct nid_path *nomix_path, *mix_path;
2466c30aa7b2STakashi Iwai 
2467c30aa7b2STakashi Iwai 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2468c30aa7b2STakashi Iwai 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2469c30aa7b2STakashi Iwai 	if (!nomix_path || !mix_path)
2470c30aa7b2STakashi Iwai 		return;
2471a1e908edSTakashi Iwai 
2472a1e908edSTakashi Iwai 	/* if HP aamix path is driven from a different DAC and the
2473a1e908edSTakashi Iwai 	 * independent HP mode is ON, can't turn on aamix path
2474a1e908edSTakashi Iwai 	 */
2475a1e908edSTakashi Iwai 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2476a1e908edSTakashi Iwai 	    mix_path->path[0] != spec->alt_dac_nid)
2477a1e908edSTakashi Iwai 		do_mix = false;
2478a1e908edSTakashi Iwai 
2479c30aa7b2STakashi Iwai 	if (do_mix) {
2480c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, false, true);
2481c30aa7b2STakashi Iwai 		snd_hda_activate_path(codec, mix_path, true, true);
248255196fffSTakashi Iwai 		path_power_down_sync(codec, nomix_path);
2483c30aa7b2STakashi Iwai 	} else {
248465033cc8STakashi Iwai 		snd_hda_activate_path(codec, mix_path, false, false);
248565033cc8STakashi Iwai 		snd_hda_activate_path(codec, nomix_path, true, false);
248655196fffSTakashi Iwai 		path_power_down_sync(codec, mix_path);
2487c30aa7b2STakashi Iwai 	}
2488c30aa7b2STakashi Iwai }
2489c30aa7b2STakashi Iwai 
2490e7fdd527STakashi Iwai /* re-initialize the output paths; only called from loopback_mixing_put() */
2491e7fdd527STakashi Iwai static void update_output_paths(struct hda_codec *codec, int num_outs,
2492e7fdd527STakashi Iwai 				const int *paths)
2493e7fdd527STakashi Iwai {
2494e7fdd527STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2495e7fdd527STakashi Iwai 	struct nid_path *path;
2496e7fdd527STakashi Iwai 	int i;
2497e7fdd527STakashi Iwai 
2498e7fdd527STakashi Iwai 	for (i = 0; i < num_outs; i++) {
2499e7fdd527STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2500e7fdd527STakashi Iwai 		if (path)
2501e7fdd527STakashi Iwai 			snd_hda_activate_path(codec, path, path->active,
2502e7fdd527STakashi Iwai 					      spec->aamix_mode);
2503e7fdd527STakashi Iwai 	}
2504e7fdd527STakashi Iwai }
2505e7fdd527STakashi Iwai 
2506c30aa7b2STakashi Iwai static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2507c30aa7b2STakashi Iwai 			       struct snd_ctl_elem_value *ucontrol)
2508c30aa7b2STakashi Iwai {
2509c30aa7b2STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2510c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2511e7fdd527STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2512c30aa7b2STakashi Iwai 	unsigned int val = ucontrol->value.enumerated.item[0];
2513c30aa7b2STakashi Iwai 
2514c30aa7b2STakashi Iwai 	if (val == spec->aamix_mode)
2515c30aa7b2STakashi Iwai 		return 0;
2516c30aa7b2STakashi Iwai 	spec->aamix_mode = val;
2517e7fdd527STakashi Iwai 	if (has_aamix_out_paths(spec)) {
2518c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->out_paths[0],
2519a1e908edSTakashi Iwai 				   spec->aamix_out_paths[0],
2520e7fdd527STakashi Iwai 				   cfg->line_out_type);
2521c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->hp_paths[0],
2522a1e908edSTakashi Iwai 				   spec->aamix_out_paths[1],
2523a1e908edSTakashi Iwai 				   AUTO_PIN_HP_OUT);
2524c30aa7b2STakashi Iwai 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2525a1e908edSTakashi Iwai 				   spec->aamix_out_paths[2],
2526a1e908edSTakashi Iwai 				   AUTO_PIN_SPEAKER_OUT);
2527e7fdd527STakashi Iwai 	} else {
2528e7fdd527STakashi Iwai 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2529e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2530e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2531e7fdd527STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2532e7fdd527STakashi Iwai 			update_output_paths(codec, cfg->speaker_outs,
2533e7fdd527STakashi Iwai 					    spec->speaker_paths);
2534e7fdd527STakashi Iwai 	}
2535c30aa7b2STakashi Iwai 	return 1;
2536c30aa7b2STakashi Iwai }
2537c30aa7b2STakashi Iwai 
2538c30aa7b2STakashi Iwai static const struct snd_kcontrol_new loopback_mixing_enum = {
2539c30aa7b2STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2540c30aa7b2STakashi Iwai 	.name = "Loopback Mixing",
2541c30aa7b2STakashi Iwai 	.info = loopback_mixing_info,
2542c30aa7b2STakashi Iwai 	.get = loopback_mixing_get,
2543c30aa7b2STakashi Iwai 	.put = loopback_mixing_put,
2544c30aa7b2STakashi Iwai };
2545c30aa7b2STakashi Iwai 
2546c30aa7b2STakashi Iwai static int create_loopback_mixing_ctl(struct hda_codec *codec)
2547c30aa7b2STakashi Iwai {
2548c30aa7b2STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2549c30aa7b2STakashi Iwai 
2550c30aa7b2STakashi Iwai 	if (!spec->mixer_nid)
2551c30aa7b2STakashi Iwai 		return 0;
2552c30aa7b2STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2553c30aa7b2STakashi Iwai 		return -ENOMEM;
2554a1e908edSTakashi Iwai 	spec->have_aamix_ctl = 1;
2555c30aa7b2STakashi Iwai 	return 0;
2556c30aa7b2STakashi Iwai }
2557c30aa7b2STakashi Iwai 
2558c30aa7b2STakashi Iwai /*
2559352f7f91STakashi Iwai  * shared headphone/mic handling
2560352f7f91STakashi Iwai  */
2561352f7f91STakashi Iwai 
2562352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec);
2563352f7f91STakashi Iwai 
2564352f7f91STakashi Iwai /* for shared I/O, change the pin-control accordingly */
2565967303daSTakashi Iwai static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2566352f7f91STakashi Iwai {
2567352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2568967303daSTakashi Iwai 	bool as_mic;
2569352f7f91STakashi Iwai 	unsigned int val;
2570967303daSTakashi Iwai 	hda_nid_t pin;
2571967303daSTakashi Iwai 
2572967303daSTakashi Iwai 	pin = spec->hp_mic_pin;
2573967303daSTakashi Iwai 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2574967303daSTakashi Iwai 
2575967303daSTakashi Iwai 	if (!force) {
2576967303daSTakashi Iwai 		val = snd_hda_codec_get_pin_target(codec, pin);
2577967303daSTakashi Iwai 		if (as_mic) {
2578967303daSTakashi Iwai 			if (val & PIN_IN)
2579967303daSTakashi Iwai 				return;
2580967303daSTakashi Iwai 		} else {
2581967303daSTakashi Iwai 			if (val & PIN_OUT)
2582967303daSTakashi Iwai 				return;
2583967303daSTakashi Iwai 		}
2584967303daSTakashi Iwai 	}
2585352f7f91STakashi Iwai 
2586352f7f91STakashi Iwai 	val = snd_hda_get_default_vref(codec, pin);
2587967303daSTakashi Iwai 	/* if the HP pin doesn't support VREF and the codec driver gives an
2588967303daSTakashi Iwai 	 * alternative pin, set up the VREF on that pin instead
2589967303daSTakashi Iwai 	 */
2590352f7f91STakashi Iwai 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2591352f7f91STakashi Iwai 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2592352f7f91STakashi Iwai 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2593352f7f91STakashi Iwai 		if (vref_val != AC_PINCTL_VREF_HIZ)
25947594aa33STakashi Iwai 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2595967303daSTakashi Iwai 						  PIN_IN | (as_mic ? vref_val : 0));
2596352f7f91STakashi Iwai 	}
2597352f7f91STakashi Iwai 
25988ba955ceSTakashi Iwai 	if (!spec->hp_mic_jack_modes) {
2599967303daSTakashi Iwai 		if (as_mic)
2600967303daSTakashi Iwai 			val |= PIN_IN;
2601967303daSTakashi Iwai 		else
2602967303daSTakashi Iwai 			val = PIN_HP;
26032c12c30dSTakashi Iwai 		set_pin_target(codec, pin, val, true);
2604963afde9STakashi Iwai 		call_hp_automute(codec, NULL);
26058ba955ceSTakashi Iwai 	}
2606352f7f91STakashi Iwai }
2607352f7f91STakashi Iwai 
2608352f7f91STakashi Iwai /* create a shared input with the headphone out */
2609967303daSTakashi Iwai static int create_hp_mic(struct hda_codec *codec)
2610352f7f91STakashi Iwai {
2611352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2612352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
2613352f7f91STakashi Iwai 	unsigned int defcfg;
2614352f7f91STakashi Iwai 	hda_nid_t nid;
2615352f7f91STakashi Iwai 
2616967303daSTakashi Iwai 	if (!spec->hp_mic) {
2617967303daSTakashi Iwai 		if (spec->suppress_hp_mic_detect)
2618352f7f91STakashi Iwai 			return 0;
2619967303daSTakashi Iwai 		/* automatic detection: only if no input or a single internal
2620967303daSTakashi Iwai 		 * input pin is found, try to detect the shared hp/mic
2621967303daSTakashi Iwai 		 */
2622967303daSTakashi Iwai 		if (cfg->num_inputs > 1)
2623967303daSTakashi Iwai 			return 0;
2624967303daSTakashi Iwai 		else if (cfg->num_inputs == 1) {
2625352f7f91STakashi Iwai 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2626352f7f91STakashi Iwai 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2627352f7f91STakashi Iwai 				return 0;
2628967303daSTakashi Iwai 		}
2629967303daSTakashi Iwai 	}
2630352f7f91STakashi Iwai 
2631967303daSTakashi Iwai 	spec->hp_mic = 0; /* clear once */
2632967303daSTakashi Iwai 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2633967303daSTakashi Iwai 		return 0;
2634967303daSTakashi Iwai 
2635967303daSTakashi Iwai 	nid = 0;
2636967303daSTakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2637967303daSTakashi Iwai 		nid = cfg->line_out_pins[0];
2638967303daSTakashi Iwai 	else if (cfg->hp_outs > 0)
2639967303daSTakashi Iwai 		nid = cfg->hp_pins[0];
2640967303daSTakashi Iwai 	if (!nid)
2641967303daSTakashi Iwai 		return 0;
2642352f7f91STakashi Iwai 
2643352f7f91STakashi Iwai 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2644352f7f91STakashi Iwai 		return 0; /* no input */
2645352f7f91STakashi Iwai 
2646967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].pin = nid;
2647967303daSTakashi Iwai 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2648cb420b11SDavid Henningsson 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2649967303daSTakashi Iwai 	cfg->num_inputs++;
2650967303daSTakashi Iwai 	spec->hp_mic = 1;
2651967303daSTakashi Iwai 	spec->hp_mic_pin = nid;
2652967303daSTakashi Iwai 	/* we can't handle auto-mic together with HP-mic */
2653967303daSTakashi Iwai 	spec->suppress_auto_mic = 1;
26544e76a883STakashi Iwai 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2655352f7f91STakashi Iwai 	return 0;
2656352f7f91STakashi Iwai }
2657352f7f91STakashi Iwai 
2658978e77e7STakashi Iwai /*
2659978e77e7STakashi Iwai  * output jack mode
2660978e77e7STakashi Iwai  */
26615f171baaSTakashi Iwai 
26625f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
26635f171baaSTakashi Iwai 
26645f171baaSTakashi Iwai static const char * const out_jack_texts[] = {
26655f171baaSTakashi Iwai 	"Line Out", "Headphone Out",
26665f171baaSTakashi Iwai };
26675f171baaSTakashi Iwai 
2668978e77e7STakashi Iwai static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2669978e77e7STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
2670978e77e7STakashi Iwai {
26715f171baaSTakashi Iwai 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2672978e77e7STakashi Iwai }
2673978e77e7STakashi Iwai 
2674978e77e7STakashi Iwai static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2675978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2676978e77e7STakashi Iwai {
2677978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2678978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2679978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2680978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 1;
2681978e77e7STakashi Iwai 	else
2682978e77e7STakashi Iwai 		ucontrol->value.enumerated.item[0] = 0;
2683978e77e7STakashi Iwai 	return 0;
2684978e77e7STakashi Iwai }
2685978e77e7STakashi Iwai 
2686978e77e7STakashi Iwai static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2687978e77e7STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
2688978e77e7STakashi Iwai {
2689978e77e7STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2690978e77e7STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
2691978e77e7STakashi Iwai 	unsigned int val;
2692978e77e7STakashi Iwai 
2693978e77e7STakashi Iwai 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2694978e77e7STakashi Iwai 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2695978e77e7STakashi Iwai 		return 0;
2696978e77e7STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2697978e77e7STakashi Iwai 	return 1;
2698978e77e7STakashi Iwai }
2699978e77e7STakashi Iwai 
2700978e77e7STakashi Iwai static const struct snd_kcontrol_new out_jack_mode_enum = {
2701978e77e7STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2702978e77e7STakashi Iwai 	.info = out_jack_mode_info,
2703978e77e7STakashi Iwai 	.get = out_jack_mode_get,
2704978e77e7STakashi Iwai 	.put = out_jack_mode_put,
2705978e77e7STakashi Iwai };
2706978e77e7STakashi Iwai 
2707978e77e7STakashi Iwai static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2708978e77e7STakashi Iwai {
2709978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2710a9c2dfc8STakashi Iwai 	const struct snd_kcontrol_new *kctl;
2711978e77e7STakashi Iwai 	int i;
2712978e77e7STakashi Iwai 
2713a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->kctls, i, kctl) {
2714978e77e7STakashi Iwai 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2715978e77e7STakashi Iwai 			return true;
2716978e77e7STakashi Iwai 	}
2717978e77e7STakashi Iwai 	return false;
2718978e77e7STakashi Iwai }
2719978e77e7STakashi Iwai 
2720978e77e7STakashi Iwai static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2721978e77e7STakashi Iwai 			       char *name, size_t name_len)
2722978e77e7STakashi Iwai {
2723978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2724978e77e7STakashi Iwai 	int idx = 0;
2725978e77e7STakashi Iwai 
2726978e77e7STakashi Iwai 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2727978e77e7STakashi Iwai 	strlcat(name, " Jack Mode", name_len);
2728978e77e7STakashi Iwai 
2729978e77e7STakashi Iwai 	for (; find_kctl_name(codec, name, idx); idx++)
2730978e77e7STakashi Iwai 		;
2731978e77e7STakashi Iwai }
2732978e77e7STakashi Iwai 
27335f171baaSTakashi Iwai static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
27345f171baaSTakashi Iwai {
27355f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2736f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
27375f171baaSTakashi Iwai 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
27385f171baaSTakashi Iwai 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
27395f171baaSTakashi Iwai 			return 2;
27405f171baaSTakashi Iwai 	}
27415f171baaSTakashi Iwai 	return 1;
27425f171baaSTakashi Iwai }
27435f171baaSTakashi Iwai 
2744978e77e7STakashi Iwai static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2745978e77e7STakashi Iwai 				 hda_nid_t *pins)
2746978e77e7STakashi Iwai {
2747978e77e7STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
2748978e77e7STakashi Iwai 	int i;
2749978e77e7STakashi Iwai 
2750978e77e7STakashi Iwai 	for (i = 0; i < num_pins; i++) {
2751978e77e7STakashi Iwai 		hda_nid_t pin = pins[i];
2752ced4cefcSTakashi Iwai 		if (pin == spec->hp_mic_pin)
27535f171baaSTakashi Iwai 			continue;
27545f171baaSTakashi Iwai 		if (get_out_jack_num_items(codec, pin) > 1) {
2755978e77e7STakashi Iwai 			struct snd_kcontrol_new *knew;
2756975cc02aSTakashi Iwai 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2757978e77e7STakashi Iwai 			get_jack_mode_name(codec, pin, name, sizeof(name));
2758978e77e7STakashi Iwai 			knew = snd_hda_gen_add_kctl(spec, name,
2759978e77e7STakashi Iwai 						    &out_jack_mode_enum);
2760978e77e7STakashi Iwai 			if (!knew)
2761978e77e7STakashi Iwai 				return -ENOMEM;
2762978e77e7STakashi Iwai 			knew->private_value = pin;
2763978e77e7STakashi Iwai 		}
2764978e77e7STakashi Iwai 	}
2765978e77e7STakashi Iwai 
2766978e77e7STakashi Iwai 	return 0;
2767978e77e7STakashi Iwai }
2768978e77e7STakashi Iwai 
276929476558STakashi Iwai /*
277029476558STakashi Iwai  * input jack mode
277129476558STakashi Iwai  */
277229476558STakashi Iwai 
277329476558STakashi Iwai /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
277429476558STakashi Iwai #define NUM_VREFS	6
277529476558STakashi Iwai 
277629476558STakashi Iwai static const char * const vref_texts[NUM_VREFS] = {
277729476558STakashi Iwai 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
277829476558STakashi Iwai 	"", "Mic 80pc Bias", "Mic 100pc Bias"
277929476558STakashi Iwai };
278029476558STakashi Iwai 
278129476558STakashi Iwai static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
278229476558STakashi Iwai {
278329476558STakashi Iwai 	unsigned int pincap;
278429476558STakashi Iwai 
278529476558STakashi Iwai 	pincap = snd_hda_query_pin_caps(codec, pin);
278629476558STakashi Iwai 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
278729476558STakashi Iwai 	/* filter out unusual vrefs */
278829476558STakashi Iwai 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
278929476558STakashi Iwai 	return pincap;
279029476558STakashi Iwai }
279129476558STakashi Iwai 
279229476558STakashi Iwai /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
279329476558STakashi Iwai static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
279429476558STakashi Iwai {
279529476558STakashi Iwai 	unsigned int i, n = 0;
279629476558STakashi Iwai 
279729476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
279829476558STakashi Iwai 		if (vref_caps & (1 << i)) {
279929476558STakashi Iwai 			if (n == item_idx)
280029476558STakashi Iwai 				return i;
280129476558STakashi Iwai 			n++;
280229476558STakashi Iwai 		}
280329476558STakashi Iwai 	}
280429476558STakashi Iwai 	return 0;
280529476558STakashi Iwai }
280629476558STakashi Iwai 
280729476558STakashi Iwai /* convert back from the vref ctl index to the enum item index */
280829476558STakashi Iwai static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
280929476558STakashi Iwai {
281029476558STakashi Iwai 	unsigned int i, n = 0;
281129476558STakashi Iwai 
281229476558STakashi Iwai 	for (i = 0; i < NUM_VREFS; i++) {
281329476558STakashi Iwai 		if (i == idx)
281429476558STakashi Iwai 			return n;
281529476558STakashi Iwai 		if (vref_caps & (1 << i))
281629476558STakashi Iwai 			n++;
281729476558STakashi Iwai 	}
281829476558STakashi Iwai 	return 0;
281929476558STakashi Iwai }
282029476558STakashi Iwai 
282129476558STakashi Iwai static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
282229476558STakashi Iwai 			     struct snd_ctl_elem_info *uinfo)
282329476558STakashi Iwai {
282429476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
282529476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
282629476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
282729476558STakashi Iwai 
282829476558STakashi Iwai 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
282929476558STakashi Iwai 				 vref_texts);
283029476558STakashi Iwai 	/* set the right text */
283129476558STakashi Iwai 	strcpy(uinfo->value.enumerated.name,
283229476558STakashi Iwai 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
283329476558STakashi Iwai 	return 0;
283429476558STakashi Iwai }
283529476558STakashi Iwai 
283629476558STakashi Iwai static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
283729476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
283829476558STakashi Iwai {
283929476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
284029476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
284129476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
284229476558STakashi Iwai 	unsigned int idx;
284329476558STakashi Iwai 
284429476558STakashi Iwai 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
284529476558STakashi Iwai 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
284629476558STakashi Iwai 	return 0;
284729476558STakashi Iwai }
284829476558STakashi Iwai 
284929476558STakashi Iwai static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
285029476558STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
285129476558STakashi Iwai {
285229476558STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
285329476558STakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
285429476558STakashi Iwai 	unsigned int vref_caps = get_vref_caps(codec, nid);
285529476558STakashi Iwai 	unsigned int val, idx;
285629476558STakashi Iwai 
285729476558STakashi Iwai 	val = snd_hda_codec_get_pin_target(codec, nid);
285829476558STakashi Iwai 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
285929476558STakashi Iwai 	if (idx == ucontrol->value.enumerated.item[0])
286029476558STakashi Iwai 		return 0;
286129476558STakashi Iwai 
286229476558STakashi Iwai 	val &= ~AC_PINCTL_VREFEN;
286329476558STakashi Iwai 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
286429476558STakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
286529476558STakashi Iwai 	return 1;
286629476558STakashi Iwai }
286729476558STakashi Iwai 
286829476558STakashi Iwai static const struct snd_kcontrol_new in_jack_mode_enum = {
286929476558STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
287029476558STakashi Iwai 	.info = in_jack_mode_info,
287129476558STakashi Iwai 	.get = in_jack_mode_get,
287229476558STakashi Iwai 	.put = in_jack_mode_put,
287329476558STakashi Iwai };
287429476558STakashi Iwai 
28755f171baaSTakashi Iwai static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
28765f171baaSTakashi Iwai {
28775f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
28785f171baaSTakashi Iwai 	int nitems = 0;
2879f811c3cfSTakashi Iwai 	if (spec->add_jack_modes)
28805f171baaSTakashi Iwai 		nitems = hweight32(get_vref_caps(codec, pin));
28815f171baaSTakashi Iwai 	return nitems ? nitems : 1;
28825f171baaSTakashi Iwai }
28835f171baaSTakashi Iwai 
288429476558STakashi Iwai static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
288529476558STakashi Iwai {
288629476558STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
288729476558STakashi Iwai 	struct snd_kcontrol_new *knew;
2888975cc02aSTakashi Iwai 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
28895f171baaSTakashi Iwai 	unsigned int defcfg;
28905f171baaSTakashi Iwai 
2891f811c3cfSTakashi Iwai 	if (pin == spec->hp_mic_pin)
2892f811c3cfSTakashi Iwai 		return 0; /* already done in create_out_jack_mode() */
289329476558STakashi Iwai 
289429476558STakashi Iwai 	/* no jack mode for fixed pins */
289529476558STakashi Iwai 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
289629476558STakashi Iwai 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
289729476558STakashi Iwai 		return 0;
289829476558STakashi Iwai 
289929476558STakashi Iwai 	/* no multiple vref caps? */
29005f171baaSTakashi Iwai 	if (get_in_jack_num_items(codec, pin) <= 1)
290129476558STakashi Iwai 		return 0;
290229476558STakashi Iwai 
290329476558STakashi Iwai 	get_jack_mode_name(codec, pin, name, sizeof(name));
290429476558STakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
290529476558STakashi Iwai 	if (!knew)
290629476558STakashi Iwai 		return -ENOMEM;
290729476558STakashi Iwai 	knew->private_value = pin;
290829476558STakashi Iwai 	return 0;
290929476558STakashi Iwai }
291029476558STakashi Iwai 
29115f171baaSTakashi Iwai /*
29125f171baaSTakashi Iwai  * HP/mic shared jack mode
29135f171baaSTakashi Iwai  */
29145f171baaSTakashi Iwai static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
29155f171baaSTakashi Iwai 				 struct snd_ctl_elem_info *uinfo)
29165f171baaSTakashi Iwai {
29175f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29185f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29195f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29205f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29215f171baaSTakashi Iwai 	const char *text = NULL;
29225f171baaSTakashi Iwai 	int idx;
29235f171baaSTakashi Iwai 
29245f171baaSTakashi Iwai 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
29255f171baaSTakashi Iwai 	uinfo->count = 1;
29265f171baaSTakashi Iwai 	uinfo->value.enumerated.items = out_jacks + in_jacks;
29275f171baaSTakashi Iwai 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
29285f171baaSTakashi Iwai 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
29295f171baaSTakashi Iwai 	idx = uinfo->value.enumerated.item;
29305f171baaSTakashi Iwai 	if (idx < out_jacks) {
29315f171baaSTakashi Iwai 		if (out_jacks > 1)
29325f171baaSTakashi Iwai 			text = out_jack_texts[idx];
29335f171baaSTakashi Iwai 		else
29345f171baaSTakashi Iwai 			text = "Headphone Out";
29355f171baaSTakashi Iwai 	} else {
29365f171baaSTakashi Iwai 		idx -= out_jacks;
29375f171baaSTakashi Iwai 		if (in_jacks > 1) {
29385f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29395f171baaSTakashi Iwai 			text = vref_texts[get_vref_idx(vref_caps, idx)];
29405f171baaSTakashi Iwai 		} else
29415f171baaSTakashi Iwai 			text = "Mic In";
29425f171baaSTakashi Iwai 	}
29435f171baaSTakashi Iwai 
29445f171baaSTakashi Iwai 	strcpy(uinfo->value.enumerated.name, text);
29455f171baaSTakashi Iwai 	return 0;
29465f171baaSTakashi Iwai }
29475f171baaSTakashi Iwai 
29485f171baaSTakashi Iwai static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
29495f171baaSTakashi Iwai {
29505f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29515f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29525f171baaSTakashi Iwai 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
29535f171baaSTakashi Iwai 	int idx = 0;
29545f171baaSTakashi Iwai 
29555f171baaSTakashi Iwai 	if (val & PIN_OUT) {
29565f171baaSTakashi Iwai 		if (out_jacks > 1 && val == PIN_HP)
29575f171baaSTakashi Iwai 			idx = 1;
29585f171baaSTakashi Iwai 	} else if (val & PIN_IN) {
29595f171baaSTakashi Iwai 		idx = out_jacks;
29605f171baaSTakashi Iwai 		if (in_jacks > 1) {
29615f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
29625f171baaSTakashi Iwai 			val &= AC_PINCTL_VREFEN;
29635f171baaSTakashi Iwai 			idx += cvt_from_vref_idx(vref_caps, val);
29645f171baaSTakashi Iwai 		}
29655f171baaSTakashi Iwai 	}
29665f171baaSTakashi Iwai 	return idx;
29675f171baaSTakashi Iwai }
29685f171baaSTakashi Iwai 
29695f171baaSTakashi Iwai static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
29705f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29715f171baaSTakashi Iwai {
29725f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29735f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29745f171baaSTakashi Iwai 	ucontrol->value.enumerated.item[0] =
29755f171baaSTakashi Iwai 		get_cur_hp_mic_jack_mode(codec, nid);
29765f171baaSTakashi Iwai 	return 0;
29775f171baaSTakashi Iwai }
29785f171baaSTakashi Iwai 
29795f171baaSTakashi Iwai static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
29805f171baaSTakashi Iwai 				struct snd_ctl_elem_value *ucontrol)
29815f171baaSTakashi Iwai {
29825f171baaSTakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
29835f171baaSTakashi Iwai 	hda_nid_t nid = kcontrol->private_value;
29845f171baaSTakashi Iwai 	int out_jacks = get_out_jack_num_items(codec, nid);
29855f171baaSTakashi Iwai 	int in_jacks = get_in_jack_num_items(codec, nid);
29865f171baaSTakashi Iwai 	unsigned int val, oldval, idx;
29875f171baaSTakashi Iwai 
29885f171baaSTakashi Iwai 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
29895f171baaSTakashi Iwai 	idx = ucontrol->value.enumerated.item[0];
29905f171baaSTakashi Iwai 	if (oldval == idx)
29915f171baaSTakashi Iwai 		return 0;
29925f171baaSTakashi Iwai 
29935f171baaSTakashi Iwai 	if (idx < out_jacks) {
29945f171baaSTakashi Iwai 		if (out_jacks > 1)
29955f171baaSTakashi Iwai 			val = idx ? PIN_HP : PIN_OUT;
29965f171baaSTakashi Iwai 		else
29975f171baaSTakashi Iwai 			val = PIN_HP;
29985f171baaSTakashi Iwai 	} else {
29995f171baaSTakashi Iwai 		idx -= out_jacks;
30005f171baaSTakashi Iwai 		if (in_jacks > 1) {
30015f171baaSTakashi Iwai 			unsigned int vref_caps = get_vref_caps(codec, nid);
30025f171baaSTakashi Iwai 			val = snd_hda_codec_get_pin_target(codec, nid);
30033f550e32STakashi Iwai 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
30043f550e32STakashi Iwai 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
30055f171baaSTakashi Iwai 		} else
300616c0cefeSTakashi Iwai 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
30075f171baaSTakashi Iwai 	}
30085f171baaSTakashi Iwai 	snd_hda_set_pin_ctl_cache(codec, nid, val);
3009963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
30108ba955ceSTakashi Iwai 
30115f171baaSTakashi Iwai 	return 1;
30125f171baaSTakashi Iwai }
30135f171baaSTakashi Iwai 
30145f171baaSTakashi Iwai static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
30155f171baaSTakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
30165f171baaSTakashi Iwai 	.info = hp_mic_jack_mode_info,
30175f171baaSTakashi Iwai 	.get = hp_mic_jack_mode_get,
30185f171baaSTakashi Iwai 	.put = hp_mic_jack_mode_put,
30195f171baaSTakashi Iwai };
30205f171baaSTakashi Iwai 
30215f171baaSTakashi Iwai static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
30225f171baaSTakashi Iwai {
30235f171baaSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
30245f171baaSTakashi Iwai 	struct snd_kcontrol_new *knew;
30255f171baaSTakashi Iwai 
30265f171baaSTakashi Iwai 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
30275f171baaSTakashi Iwai 				    &hp_mic_jack_mode_enum);
30285f171baaSTakashi Iwai 	if (!knew)
30295f171baaSTakashi Iwai 		return -ENOMEM;
30305f171baaSTakashi Iwai 	knew->private_value = pin;
30318ba955ceSTakashi Iwai 	spec->hp_mic_jack_modes = 1;
30325f171baaSTakashi Iwai 	return 0;
30335f171baaSTakashi Iwai }
3034352f7f91STakashi Iwai 
3035352f7f91STakashi Iwai /*
3036352f7f91STakashi Iwai  * Parse input paths
3037352f7f91STakashi Iwai  */
3038352f7f91STakashi Iwai 
3039352f7f91STakashi Iwai /* add the powersave loopback-list entry */
30400186f4f4STakashi Iwai static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
3041352f7f91STakashi Iwai {
3042352f7f91STakashi Iwai 	struct hda_amp_list *list;
3043352f7f91STakashi Iwai 
30440186f4f4STakashi Iwai 	list = snd_array_new(&spec->loopback_list);
30450186f4f4STakashi Iwai 	if (!list)
30460186f4f4STakashi Iwai 		return -ENOMEM;
3047352f7f91STakashi Iwai 	list->nid = mix;
3048352f7f91STakashi Iwai 	list->dir = HDA_INPUT;
3049352f7f91STakashi Iwai 	list->idx = idx;
30500186f4f4STakashi Iwai 	spec->loopback.amplist = spec->loopback_list.list;
30510186f4f4STakashi Iwai 	return 0;
3052cb53c626STakashi Iwai }
3053cb53c626STakashi Iwai 
30542ded3e5bSTakashi Iwai /* return true if either a volume or a mute amp is found for the given
30552ded3e5bSTakashi Iwai  * aamix path; the amp has to be either in the mixer node or its direct leaf
30562ded3e5bSTakashi Iwai  */
30572ded3e5bSTakashi Iwai static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
30582ded3e5bSTakashi Iwai 				   hda_nid_t pin, unsigned int *mix_val,
30592ded3e5bSTakashi Iwai 				   unsigned int *mute_val)
30602ded3e5bSTakashi Iwai {
30612ded3e5bSTakashi Iwai 	int idx, num_conns;
30622ded3e5bSTakashi Iwai 	const hda_nid_t *list;
30632ded3e5bSTakashi Iwai 	hda_nid_t nid;
30642ded3e5bSTakashi Iwai 
30652ded3e5bSTakashi Iwai 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
30662ded3e5bSTakashi Iwai 	if (idx < 0)
30672ded3e5bSTakashi Iwai 		return false;
30682ded3e5bSTakashi Iwai 
30692ded3e5bSTakashi Iwai 	*mix_val = *mute_val = 0;
30702ded3e5bSTakashi Iwai 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
30712ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30722ded3e5bSTakashi Iwai 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
30732ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
30742ded3e5bSTakashi Iwai 	if (*mix_val && *mute_val)
30752ded3e5bSTakashi Iwai 		return true;
30762ded3e5bSTakashi Iwai 
30772ded3e5bSTakashi Iwai 	/* check leaf node */
30782ded3e5bSTakashi Iwai 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
30792ded3e5bSTakashi Iwai 	if (num_conns < idx)
30802ded3e5bSTakashi Iwai 		return false;
30812ded3e5bSTakashi Iwai 	nid = list[idx];
308243a8e50aSTakashi Iwai 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
308343a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
30842ded3e5bSTakashi Iwai 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
308543a8e50aSTakashi Iwai 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
308643a8e50aSTakashi Iwai 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
30872ded3e5bSTakashi Iwai 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
30882ded3e5bSTakashi Iwai 
30892ded3e5bSTakashi Iwai 	return *mix_val || *mute_val;
30902ded3e5bSTakashi Iwai }
30912ded3e5bSTakashi Iwai 
3092352f7f91STakashi Iwai /* create input playback/capture controls for the given pin */
3093196c1766STakashi Iwai static int new_analog_input(struct hda_codec *codec, int input_idx,
3094196c1766STakashi Iwai 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3095352f7f91STakashi Iwai 			    hda_nid_t mix_nid)
30961da177e4SLinus Torvalds {
3097352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3098352f7f91STakashi Iwai 	struct nid_path *path;
30992ded3e5bSTakashi Iwai 	unsigned int mix_val, mute_val;
3100352f7f91STakashi Iwai 	int err, idx;
31011da177e4SLinus Torvalds 
31022ded3e5bSTakashi Iwai 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
31032ded3e5bSTakashi Iwai 		return 0;
3104352f7f91STakashi Iwai 
31053ca529d3STakashi Iwai 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3106352f7f91STakashi Iwai 	if (!path)
3107352f7f91STakashi Iwai 		return -EINVAL;
31084e76a883STakashi Iwai 	print_nid_path(codec, "loopback", path);
3109196c1766STakashi Iwai 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3110352f7f91STakashi Iwai 
3111352f7f91STakashi Iwai 	idx = path->idx[path->depth - 1];
31122ded3e5bSTakashi Iwai 	if (mix_val) {
31132ded3e5bSTakashi Iwai 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3114d13bd412STakashi Iwai 		if (err < 0)
31151da177e4SLinus Torvalds 			return err;
31162ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
31171da177e4SLinus Torvalds 	}
31181da177e4SLinus Torvalds 
31192ded3e5bSTakashi Iwai 	if (mute_val) {
31202ded3e5bSTakashi Iwai 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3121d13bd412STakashi Iwai 		if (err < 0)
31221da177e4SLinus Torvalds 			return err;
31232ded3e5bSTakashi Iwai 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
31241da177e4SLinus Torvalds 	}
31251da177e4SLinus Torvalds 
3126352f7f91STakashi Iwai 	path->active = true;
3127e6feb5d0STakashi Iwai 	path->stream_enabled = true; /* no DAC/ADC involved */
31280186f4f4STakashi Iwai 	err = add_loopback_list(spec, mix_nid, idx);
31290186f4f4STakashi Iwai 	if (err < 0)
31300186f4f4STakashi Iwai 		return err;
3131e4a395e7STakashi Iwai 
3132e4a395e7STakashi Iwai 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3133e4a395e7STakashi Iwai 	    !spec->loopback_merge_path) {
3134e4a395e7STakashi Iwai 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3135e4a395e7STakashi Iwai 					    spec->mixer_merge_nid, 0);
3136e4a395e7STakashi Iwai 		if (path) {
31374e76a883STakashi Iwai 			print_nid_path(codec, "loopback-merge", path);
3138e4a395e7STakashi Iwai 			path->active = true;
31396b275b14STakashi Iwai 			path->pin_fixed = true; /* static route */
3140e6feb5d0STakashi Iwai 			path->stream_enabled = true; /* no DAC/ADC involved */
3141e4a395e7STakashi Iwai 			spec->loopback_merge_path =
3142e4a395e7STakashi Iwai 				snd_hda_get_path_idx(codec, path);
3143e4a395e7STakashi Iwai 		}
3144e4a395e7STakashi Iwai 	}
3145e4a395e7STakashi Iwai 
3146352f7f91STakashi Iwai 	return 0;
31471da177e4SLinus Torvalds }
31481da177e4SLinus Torvalds 
3149352f7f91STakashi Iwai static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
31501da177e4SLinus Torvalds {
3151352f7f91STakashi Iwai 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3152352f7f91STakashi Iwai 	return (pincap & AC_PINCAP_IN) != 0;
3153352f7f91STakashi Iwai }
3154352f7f91STakashi Iwai 
3155352f7f91STakashi Iwai /* Parse the codec tree and retrieve ADCs */
3156352f7f91STakashi Iwai static int fill_adc_nids(struct hda_codec *codec)
3157352f7f91STakashi Iwai {
3158352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3159352f7f91STakashi Iwai 	hda_nid_t nid;
3160352f7f91STakashi Iwai 	hda_nid_t *adc_nids = spec->adc_nids;
3161352f7f91STakashi Iwai 	int max_nums = ARRAY_SIZE(spec->adc_nids);
31627639a06cSTakashi Iwai 	int nums = 0;
3163352f7f91STakashi Iwai 
31647639a06cSTakashi Iwai 	for_each_hda_codec_node(nid, codec) {
3165352f7f91STakashi Iwai 		unsigned int caps = get_wcaps(codec, nid);
3166352f7f91STakashi Iwai 		int type = get_wcaps_type(caps);
3167352f7f91STakashi Iwai 
3168352f7f91STakashi Iwai 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3169352f7f91STakashi Iwai 			continue;
3170352f7f91STakashi Iwai 		adc_nids[nums] = nid;
3171352f7f91STakashi Iwai 		if (++nums >= max_nums)
3172352f7f91STakashi Iwai 			break;
3173352f7f91STakashi Iwai 	}
3174352f7f91STakashi Iwai 	spec->num_adc_nids = nums;
31750ffd534eSTakashi Iwai 
31760ffd534eSTakashi Iwai 	/* copy the detected ADCs to all_adcs[] */
31770ffd534eSTakashi Iwai 	spec->num_all_adcs = nums;
31780ffd534eSTakashi Iwai 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
31790ffd534eSTakashi Iwai 
3180352f7f91STakashi Iwai 	return nums;
3181352f7f91STakashi Iwai }
3182352f7f91STakashi Iwai 
3183352f7f91STakashi Iwai /* filter out invalid adc_nids that don't give all active input pins;
3184352f7f91STakashi Iwai  * if needed, check whether dynamic ADC-switching is available
3185352f7f91STakashi Iwai  */
3186352f7f91STakashi Iwai static int check_dyn_adc_switch(struct hda_codec *codec)
3187352f7f91STakashi Iwai {
3188352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3189352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
31903a65bcdcSTakashi Iwai 	unsigned int ok_bits;
3191352f7f91STakashi Iwai 	int i, n, nums;
3192352f7f91STakashi Iwai 
3193352f7f91STakashi Iwai 	nums = 0;
31943a65bcdcSTakashi Iwai 	ok_bits = 0;
3195352f7f91STakashi Iwai 	for (n = 0; n < spec->num_adc_nids; n++) {
3196352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
31973a65bcdcSTakashi Iwai 			if (!spec->input_paths[i][n])
3198352f7f91STakashi Iwai 				break;
3199352f7f91STakashi Iwai 		}
32003a65bcdcSTakashi Iwai 		if (i >= imux->num_items) {
32013a65bcdcSTakashi Iwai 			ok_bits |= (1 << n);
32023a65bcdcSTakashi Iwai 			nums++;
32033a65bcdcSTakashi Iwai 		}
3204352f7f91STakashi Iwai 	}
3205352f7f91STakashi Iwai 
32063a65bcdcSTakashi Iwai 	if (!ok_bits) {
3207352f7f91STakashi Iwai 		/* check whether ADC-switch is possible */
3208352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3209352f7f91STakashi Iwai 			for (n = 0; n < spec->num_adc_nids; n++) {
32103a65bcdcSTakashi Iwai 				if (spec->input_paths[i][n]) {
3211352f7f91STakashi Iwai 					spec->dyn_adc_idx[i] = n;
3212352f7f91STakashi Iwai 					break;
3213352f7f91STakashi Iwai 				}
3214352f7f91STakashi Iwai 			}
3215352f7f91STakashi Iwai 		}
3216352f7f91STakashi Iwai 
32174e76a883STakashi Iwai 		codec_dbg(codec, "enabling ADC switching\n");
3218352f7f91STakashi Iwai 		spec->dyn_adc_switch = 1;
3219352f7f91STakashi Iwai 	} else if (nums != spec->num_adc_nids) {
32203a65bcdcSTakashi Iwai 		/* shrink the invalid adcs and input paths */
32213a65bcdcSTakashi Iwai 		nums = 0;
32223a65bcdcSTakashi Iwai 		for (n = 0; n < spec->num_adc_nids; n++) {
32233a65bcdcSTakashi Iwai 			if (!(ok_bits & (1 << n)))
32243a65bcdcSTakashi Iwai 				continue;
32253a65bcdcSTakashi Iwai 			if (n != nums) {
32263a65bcdcSTakashi Iwai 				spec->adc_nids[nums] = spec->adc_nids[n];
3227980428ceSTakashi Iwai 				for (i = 0; i < imux->num_items; i++) {
3228980428ceSTakashi Iwai 					invalidate_nid_path(codec,
3229980428ceSTakashi Iwai 						spec->input_paths[i][nums]);
32303a65bcdcSTakashi Iwai 					spec->input_paths[i][nums] =
32313a65bcdcSTakashi Iwai 						spec->input_paths[i][n];
3232a8f20fd2SHui Wang 					spec->input_paths[i][n] = 0;
32333a65bcdcSTakashi Iwai 				}
3234980428ceSTakashi Iwai 			}
32353a65bcdcSTakashi Iwai 			nums++;
32363a65bcdcSTakashi Iwai 		}
3237352f7f91STakashi Iwai 		spec->num_adc_nids = nums;
3238352f7f91STakashi Iwai 	}
3239352f7f91STakashi Iwai 
3240967303daSTakashi Iwai 	if (imux->num_items == 1 ||
3241967303daSTakashi Iwai 	    (imux->num_items == 2 && spec->hp_mic)) {
32424e76a883STakashi Iwai 		codec_dbg(codec, "reducing to a single ADC\n");
3243352f7f91STakashi Iwai 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3244352f7f91STakashi Iwai 	}
3245352f7f91STakashi Iwai 
3246352f7f91STakashi Iwai 	/* single index for individual volumes ctls */
3247352f7f91STakashi Iwai 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3248352f7f91STakashi Iwai 		spec->num_adc_nids = 1;
3249352f7f91STakashi Iwai 
32501da177e4SLinus Torvalds 	return 0;
32511da177e4SLinus Torvalds }
32521da177e4SLinus Torvalds 
3253f3fc0b0bSTakashi Iwai /* parse capture source paths from the given pin and create imux items */
3254f3fc0b0bSTakashi Iwai static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
32559dba205bSTakashi Iwai 				int cfg_idx, int num_adcs,
32569dba205bSTakashi Iwai 				const char *label, int anchor)
3257f3fc0b0bSTakashi Iwai {
3258f3fc0b0bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3259f3fc0b0bSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3260f3fc0b0bSTakashi Iwai 	int imux_idx = imux->num_items;
3261f3fc0b0bSTakashi Iwai 	bool imux_added = false;
3262f3fc0b0bSTakashi Iwai 	int c;
3263f3fc0b0bSTakashi Iwai 
3264f3fc0b0bSTakashi Iwai 	for (c = 0; c < num_adcs; c++) {
3265f3fc0b0bSTakashi Iwai 		struct nid_path *path;
3266f3fc0b0bSTakashi Iwai 		hda_nid_t adc = spec->adc_nids[c];
3267f3fc0b0bSTakashi Iwai 
3268f3fc0b0bSTakashi Iwai 		if (!is_reachable_path(codec, pin, adc))
3269f3fc0b0bSTakashi Iwai 			continue;
3270f3fc0b0bSTakashi Iwai 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3271f3fc0b0bSTakashi Iwai 		if (!path)
3272f3fc0b0bSTakashi Iwai 			continue;
32734e76a883STakashi Iwai 		print_nid_path(codec, "input", path);
3274f3fc0b0bSTakashi Iwai 		spec->input_paths[imux_idx][c] =
3275f3fc0b0bSTakashi Iwai 			snd_hda_get_path_idx(codec, path);
3276f3fc0b0bSTakashi Iwai 
3277f3fc0b0bSTakashi Iwai 		if (!imux_added) {
3278967303daSTakashi Iwai 			if (spec->hp_mic_pin == pin)
3279967303daSTakashi Iwai 				spec->hp_mic_mux_idx = imux->num_items;
3280f3fc0b0bSTakashi Iwai 			spec->imux_pins[imux->num_items] = pin;
32816194b99dSTakashi Iwai 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3282f3fc0b0bSTakashi Iwai 			imux_added = true;
3283f1e762ddSTakashi Iwai 			if (spec->dyn_adc_switch)
3284f1e762ddSTakashi Iwai 				spec->dyn_adc_idx[imux_idx] = c;
3285f3fc0b0bSTakashi Iwai 		}
3286f3fc0b0bSTakashi Iwai 	}
3287f3fc0b0bSTakashi Iwai 
3288f3fc0b0bSTakashi Iwai 	return 0;
3289f3fc0b0bSTakashi Iwai }
3290f3fc0b0bSTakashi Iwai 
32911da177e4SLinus Torvalds /*
3292352f7f91STakashi Iwai  * create playback/capture controls for input pins
32931da177e4SLinus Torvalds  */
32949dba205bSTakashi Iwai 
3295c970042cSTakashi Iwai /* fill the label for each input at first */
3296c970042cSTakashi Iwai static int fill_input_pin_labels(struct hda_codec *codec)
3297c970042cSTakashi Iwai {
3298c970042cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3299c970042cSTakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3300c970042cSTakashi Iwai 	int i;
3301c970042cSTakashi Iwai 
3302c970042cSTakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3303c970042cSTakashi Iwai 		hda_nid_t pin = cfg->inputs[i].pin;
3304c970042cSTakashi Iwai 		const char *label;
3305c970042cSTakashi Iwai 		int j, idx;
3306c970042cSTakashi Iwai 
3307c970042cSTakashi Iwai 		if (!is_input_pin(codec, pin))
3308c970042cSTakashi Iwai 			continue;
3309c970042cSTakashi Iwai 
3310c970042cSTakashi Iwai 		label = hda_get_autocfg_input_label(codec, cfg, i);
3311c970042cSTakashi Iwai 		idx = 0;
33128e8db7f1SDavid Henningsson 		for (j = i - 1; j >= 0; j--) {
3313c970042cSTakashi Iwai 			if (spec->input_labels[j] &&
3314c970042cSTakashi Iwai 			    !strcmp(spec->input_labels[j], label)) {
3315c970042cSTakashi Iwai 				idx = spec->input_label_idxs[j] + 1;
3316c970042cSTakashi Iwai 				break;
3317c970042cSTakashi Iwai 			}
3318c970042cSTakashi Iwai 		}
3319c970042cSTakashi Iwai 
3320c970042cSTakashi Iwai 		spec->input_labels[i] = label;
3321c970042cSTakashi Iwai 		spec->input_label_idxs[i] = idx;
3322c970042cSTakashi Iwai 	}
3323c970042cSTakashi Iwai 
3324c970042cSTakashi Iwai 	return 0;
3325c970042cSTakashi Iwai }
3326c970042cSTakashi Iwai 
33279dba205bSTakashi Iwai #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
33289dba205bSTakashi Iwai 
3329352f7f91STakashi Iwai static int create_input_ctls(struct hda_codec *codec)
3330a7da6ce5STakashi Iwai {
3331352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3332352f7f91STakashi Iwai 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3333352f7f91STakashi Iwai 	hda_nid_t mixer = spec->mixer_nid;
3334352f7f91STakashi Iwai 	int num_adcs;
3335c970042cSTakashi Iwai 	int i, err;
33362c12c30dSTakashi Iwai 	unsigned int val;
3337a7da6ce5STakashi Iwai 
3338352f7f91STakashi Iwai 	num_adcs = fill_adc_nids(codec);
3339352f7f91STakashi Iwai 	if (num_adcs < 0)
3340352f7f91STakashi Iwai 		return 0;
3341352f7f91STakashi Iwai 
3342c970042cSTakashi Iwai 	err = fill_input_pin_labels(codec);
3343c970042cSTakashi Iwai 	if (err < 0)
3344c970042cSTakashi Iwai 		return err;
3345c970042cSTakashi Iwai 
3346352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3347352f7f91STakashi Iwai 		hda_nid_t pin;
3348352f7f91STakashi Iwai 
3349352f7f91STakashi Iwai 		pin = cfg->inputs[i].pin;
3350352f7f91STakashi Iwai 		if (!is_input_pin(codec, pin))
3351352f7f91STakashi Iwai 			continue;
3352352f7f91STakashi Iwai 
33532c12c30dSTakashi Iwai 		val = PIN_IN;
33542c12c30dSTakashi Iwai 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
33552c12c30dSTakashi Iwai 			val |= snd_hda_get_default_vref(codec, pin);
33563e1b0c4aSTakashi Iwai 		if (pin != spec->hp_mic_pin &&
33573e1b0c4aSTakashi Iwai 		    !snd_hda_codec_get_pin_target(codec, pin))
33582c12c30dSTakashi Iwai 			set_pin_target(codec, pin, val, false);
33592c12c30dSTakashi Iwai 
3360352f7f91STakashi Iwai 		if (mixer) {
3361352f7f91STakashi Iwai 			if (is_reachable_path(codec, pin, mixer)) {
3362196c1766STakashi Iwai 				err = new_analog_input(codec, i, pin,
3363c970042cSTakashi Iwai 						       spec->input_labels[i],
3364c970042cSTakashi Iwai 						       spec->input_label_idxs[i],
3365c970042cSTakashi Iwai 						       mixer);
3366a7da6ce5STakashi Iwai 				if (err < 0)
3367a7da6ce5STakashi Iwai 					return err;
3368a7da6ce5STakashi Iwai 			}
3369352f7f91STakashi Iwai 		}
3370352f7f91STakashi Iwai 
3371c970042cSTakashi Iwai 		err = parse_capture_source(codec, pin, i, num_adcs,
3372c970042cSTakashi Iwai 					   spec->input_labels[i], -mixer);
3373f3fc0b0bSTakashi Iwai 		if (err < 0)
3374f3fc0b0bSTakashi Iwai 			return err;
337529476558STakashi Iwai 
3376f811c3cfSTakashi Iwai 		if (spec->add_jack_modes) {
337729476558STakashi Iwai 			err = create_in_jack_mode(codec, pin);
337829476558STakashi Iwai 			if (err < 0)
337929476558STakashi Iwai 				return err;
338029476558STakashi Iwai 		}
3381352f7f91STakashi Iwai 	}
3382f3fc0b0bSTakashi Iwai 
3383f1e762ddSTakashi Iwai 	/* add stereo mix when explicitly enabled via hint */
338474f14b36STakashi Iwai 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
33859dba205bSTakashi Iwai 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3386f3fc0b0bSTakashi Iwai 					   "Stereo Mix", 0);
3387f3fc0b0bSTakashi Iwai 		if (err < 0)
3388f3fc0b0bSTakashi Iwai 			return err;
338982d04e10STakashi Iwai 		else
339082d04e10STakashi Iwai 			spec->suppress_auto_mic = 1;
3391352f7f91STakashi Iwai 	}
3392352f7f91STakashi Iwai 
3393a7da6ce5STakashi Iwai 	return 0;
3394a7da6ce5STakashi Iwai }
3395a7da6ce5STakashi Iwai 
33961da177e4SLinus Torvalds 
3397352f7f91STakashi Iwai /*
3398352f7f91STakashi Iwai  * input source mux
3399352f7f91STakashi Iwai  */
3400352f7f91STakashi Iwai 
3401c697b716STakashi Iwai /* get the input path specified by the given adc and imux indices */
3402c697b716STakashi Iwai static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3403352f7f91STakashi Iwai {
3404352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3405b56fa1edSDavid Henningsson 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3406b56fa1edSDavid Henningsson 		snd_BUG();
3407b56fa1edSDavid Henningsson 		return NULL;
3408b56fa1edSDavid Henningsson 	}
3409352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3410352f7f91STakashi Iwai 		adc_idx = spec->dyn_adc_idx[imux_idx];
3411d3d982f7SDavid Henningsson 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3412b56fa1edSDavid Henningsson 		snd_BUG();
3413b56fa1edSDavid Henningsson 		return NULL;
3414b56fa1edSDavid Henningsson 	}
3415c697b716STakashi Iwai 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
341697ec558aSTakashi Iwai }
3417352f7f91STakashi Iwai 
3418352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3419352f7f91STakashi Iwai 		      unsigned int idx);
3420352f7f91STakashi Iwai 
3421352f7f91STakashi Iwai static int mux_enum_info(struct snd_kcontrol *kcontrol,
3422352f7f91STakashi Iwai 			 struct snd_ctl_elem_info *uinfo)
3423352f7f91STakashi Iwai {
3424352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3425352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3426352f7f91STakashi Iwai 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3427352f7f91STakashi Iwai }
3428352f7f91STakashi Iwai 
3429352f7f91STakashi Iwai static int mux_enum_get(struct snd_kcontrol *kcontrol,
3430352f7f91STakashi Iwai 			struct snd_ctl_elem_value *ucontrol)
3431352f7f91STakashi Iwai {
3432352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3433352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
34342a8d5391STakashi Iwai 	/* the ctls are created at once with multiple counts */
34352a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3436352f7f91STakashi Iwai 
3437352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
34381da177e4SLinus Torvalds 	return 0;
34391da177e4SLinus Torvalds }
34401da177e4SLinus Torvalds 
3441352f7f91STakashi Iwai static int mux_enum_put(struct snd_kcontrol *kcontrol,
3442352f7f91STakashi Iwai 			    struct snd_ctl_elem_value *ucontrol)
34431da177e4SLinus Torvalds {
3444352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
34452a8d5391STakashi Iwai 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3446352f7f91STakashi Iwai 	return mux_select(codec, adc_idx,
3447352f7f91STakashi Iwai 			  ucontrol->value.enumerated.item[0]);
3448352f7f91STakashi Iwai }
3449352f7f91STakashi Iwai 
3450352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_src_temp = {
34511da177e4SLinus Torvalds 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3452352f7f91STakashi Iwai 	.name = "Input Source",
3453352f7f91STakashi Iwai 	.info = mux_enum_info,
3454352f7f91STakashi Iwai 	.get = mux_enum_get,
3455352f7f91STakashi Iwai 	.put = mux_enum_put,
34561da177e4SLinus Torvalds };
3457071c73adSTakashi Iwai 
345847d46abbSTakashi Iwai /*
345947d46abbSTakashi Iwai  * capture volume and capture switch ctls
346047d46abbSTakashi Iwai  */
346147d46abbSTakashi Iwai 
3462352f7f91STakashi Iwai typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3463352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol);
3464071c73adSTakashi Iwai 
346547d46abbSTakashi Iwai /* call the given amp update function for all amps in the imux list at once */
3466352f7f91STakashi Iwai static int cap_put_caller(struct snd_kcontrol *kcontrol,
3467352f7f91STakashi Iwai 			  struct snd_ctl_elem_value *ucontrol,
3468352f7f91STakashi Iwai 			  put_call_t func, int type)
3469352f7f91STakashi Iwai {
3470352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3471352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3472352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
3473352f7f91STakashi Iwai 	struct nid_path *path;
3474a2befe93SJaroslav Kysela 	int i, adc_idx, ret, err = 0;
3475071c73adSTakashi Iwai 
3476352f7f91STakashi Iwai 	imux = &spec->input_mux;
3477a053d1e3SDavid Henningsson 	adc_idx = kcontrol->id.index;
3478352f7f91STakashi Iwai 	mutex_lock(&codec->control_mutex);
3479352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3480c697b716STakashi Iwai 		path = get_input_path(codec, adc_idx, i);
3481c697b716STakashi Iwai 		if (!path || !path->ctls[type])
3482352f7f91STakashi Iwai 			continue;
3483352f7f91STakashi Iwai 		kcontrol->private_value = path->ctls[type];
3484a2befe93SJaroslav Kysela 		ret = func(kcontrol, ucontrol);
3485a2befe93SJaroslav Kysela 		if (ret < 0) {
3486a2befe93SJaroslav Kysela 			err = ret;
3487a551d914STakashi Iwai 			break;
3488352f7f91STakashi Iwai 		}
3489a2befe93SJaroslav Kysela 		if (ret > 0)
3490a2befe93SJaroslav Kysela 			err = 1;
3491a2befe93SJaroslav Kysela 	}
3492352f7f91STakashi Iwai 	mutex_unlock(&codec->control_mutex);
3493352f7f91STakashi Iwai 	if (err >= 0 && spec->cap_sync_hook)
34947fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3495352f7f91STakashi Iwai 	return err;
3496352f7f91STakashi Iwai }
3497352f7f91STakashi Iwai 
3498352f7f91STakashi Iwai /* capture volume ctl callbacks */
3499352f7f91STakashi Iwai #define cap_vol_info		snd_hda_mixer_amp_volume_info
3500352f7f91STakashi Iwai #define cap_vol_get		snd_hda_mixer_amp_volume_get
3501352f7f91STakashi Iwai #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3502352f7f91STakashi Iwai 
3503352f7f91STakashi Iwai static int cap_vol_put(struct snd_kcontrol *kcontrol,
3504352f7f91STakashi Iwai 		       struct snd_ctl_elem_value *ucontrol)
3505352f7f91STakashi Iwai {
3506352f7f91STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3507352f7f91STakashi Iwai 			      snd_hda_mixer_amp_volume_put,
3508352f7f91STakashi Iwai 			      NID_PATH_VOL_CTL);
3509352f7f91STakashi Iwai }
3510352f7f91STakashi Iwai 
3511352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_vol_temp = {
3512352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3513352f7f91STakashi Iwai 	.name = "Capture Volume",
3514352f7f91STakashi Iwai 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3515352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3516352f7f91STakashi Iwai 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3517352f7f91STakashi Iwai 	.info = cap_vol_info,
3518352f7f91STakashi Iwai 	.get = cap_vol_get,
3519352f7f91STakashi Iwai 	.put = cap_vol_put,
3520352f7f91STakashi Iwai 	.tlv = { .c = cap_vol_tlv },
3521352f7f91STakashi Iwai };
3522352f7f91STakashi Iwai 
3523352f7f91STakashi Iwai /* capture switch ctl callbacks */
3524352f7f91STakashi Iwai #define cap_sw_info		snd_ctl_boolean_stereo_info
3525352f7f91STakashi Iwai #define cap_sw_get		snd_hda_mixer_amp_switch_get
3526352f7f91STakashi Iwai 
3527352f7f91STakashi Iwai static int cap_sw_put(struct snd_kcontrol *kcontrol,
3528352f7f91STakashi Iwai 		      struct snd_ctl_elem_value *ucontrol)
3529352f7f91STakashi Iwai {
3530a90229e0STakashi Iwai 	return cap_put_caller(kcontrol, ucontrol,
3531352f7f91STakashi Iwai 			      snd_hda_mixer_amp_switch_put,
3532352f7f91STakashi Iwai 			      NID_PATH_MUTE_CTL);
3533352f7f91STakashi Iwai }
3534352f7f91STakashi Iwai 
3535352f7f91STakashi Iwai static const struct snd_kcontrol_new cap_sw_temp = {
3536352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3537352f7f91STakashi Iwai 	.name = "Capture Switch",
353808a4b904STakashi Iwai 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
3539352f7f91STakashi Iwai 	.info = cap_sw_info,
3540352f7f91STakashi Iwai 	.get = cap_sw_get,
3541352f7f91STakashi Iwai 	.put = cap_sw_put,
3542352f7f91STakashi Iwai };
3543352f7f91STakashi Iwai 
3544352f7f91STakashi Iwai static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3545352f7f91STakashi Iwai {
3546352f7f91STakashi Iwai 	hda_nid_t nid;
3547352f7f91STakashi Iwai 	int i, depth;
3548352f7f91STakashi Iwai 
3549352f7f91STakashi Iwai 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3550352f7f91STakashi Iwai 	for (depth = 0; depth < 3; depth++) {
3551352f7f91STakashi Iwai 		if (depth >= path->depth)
3552352f7f91STakashi Iwai 			return -EINVAL;
3553352f7f91STakashi Iwai 		i = path->depth - depth - 1;
3554352f7f91STakashi Iwai 		nid = path->path[i];
3555352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3556352f7f91STakashi Iwai 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3557352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3558352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3559352f7f91STakashi Iwai 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3560352f7f91STakashi Iwai 				int idx = path->idx[i];
3561352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3562352f7f91STakashi Iwai 					idx = 0;
3563352f7f91STakashi Iwai 				path->ctls[NID_PATH_VOL_CTL] =
3564352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3565352f7f91STakashi Iwai 			}
3566352f7f91STakashi Iwai 		}
3567352f7f91STakashi Iwai 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3568352f7f91STakashi Iwai 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3569352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3570352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3571352f7f91STakashi Iwai 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3572352f7f91STakashi Iwai 				int idx = path->idx[i];
3573352f7f91STakashi Iwai 				if (!depth && codec->single_adc_amp)
3574352f7f91STakashi Iwai 					idx = 0;
3575352f7f91STakashi Iwai 				path->ctls[NID_PATH_MUTE_CTL] =
3576352f7f91STakashi Iwai 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3577352f7f91STakashi Iwai 			}
3578352f7f91STakashi Iwai 		}
3579352f7f91STakashi Iwai 	}
3580352f7f91STakashi Iwai 	return 0;
3581352f7f91STakashi Iwai }
3582352f7f91STakashi Iwai 
3583352f7f91STakashi Iwai static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3584352f7f91STakashi Iwai {
3585352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3586352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
3587352f7f91STakashi Iwai 	unsigned int val;
3588352f7f91STakashi Iwai 	int i;
3589352f7f91STakashi Iwai 
3590352f7f91STakashi Iwai 	if (!spec->inv_dmic_split)
3591352f7f91STakashi Iwai 		return false;
3592352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
3593352f7f91STakashi Iwai 		if (cfg->inputs[i].pin != nid)
3594352f7f91STakashi Iwai 			continue;
3595352f7f91STakashi Iwai 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3596352f7f91STakashi Iwai 			return false;
3597352f7f91STakashi Iwai 		val = snd_hda_codec_get_pincfg(codec, nid);
3598352f7f91STakashi Iwai 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3599352f7f91STakashi Iwai 	}
3600352f7f91STakashi Iwai 	return false;
3601352f7f91STakashi Iwai }
3602352f7f91STakashi Iwai 
3603a90229e0STakashi Iwai /* capture switch put callback for a single control with hook call */
3604a35bd1e3STakashi Iwai static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3605a35bd1e3STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
3606a35bd1e3STakashi Iwai {
3607a35bd1e3STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3608a35bd1e3STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3609a35bd1e3STakashi Iwai 	int ret;
3610a35bd1e3STakashi Iwai 
3611a35bd1e3STakashi Iwai 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3612a35bd1e3STakashi Iwai 	if (ret < 0)
3613a35bd1e3STakashi Iwai 		return ret;
3614a35bd1e3STakashi Iwai 
3615a90229e0STakashi Iwai 	if (spec->cap_sync_hook)
36167fe30711STakashi Iwai 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3617a35bd1e3STakashi Iwai 
3618a35bd1e3STakashi Iwai 	return ret;
3619a35bd1e3STakashi Iwai }
3620a35bd1e3STakashi Iwai 
3621352f7f91STakashi Iwai static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3622352f7f91STakashi Iwai 			      int idx, bool is_switch, unsigned int ctl,
3623352f7f91STakashi Iwai 			      bool inv_dmic)
3624352f7f91STakashi Iwai {
3625352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3626975cc02aSTakashi Iwai 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3627352f7f91STakashi Iwai 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3628352f7f91STakashi Iwai 	const char *sfx = is_switch ? "Switch" : "Volume";
3629352f7f91STakashi Iwai 	unsigned int chs = inv_dmic ? 1 : 3;
3630a35bd1e3STakashi Iwai 	struct snd_kcontrol_new *knew;
3631352f7f91STakashi Iwai 
3632352f7f91STakashi Iwai 	if (!ctl)
3633352f7f91STakashi Iwai 		return 0;
3634352f7f91STakashi Iwai 
3635352f7f91STakashi Iwai 	if (label)
3636352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3637352f7f91STakashi Iwai 			 "%s Capture %s", label, sfx);
3638352f7f91STakashi Iwai 	else
3639352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3640352f7f91STakashi Iwai 			 "Capture %s", sfx);
3641a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3642352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, chs));
3643a35bd1e3STakashi Iwai 	if (!knew)
3644a35bd1e3STakashi Iwai 		return -ENOMEM;
3645e65bf997SJaroslav Kysela 	if (is_switch) {
3646a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3647e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3648e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3649e65bf997SJaroslav Kysela 	}
3650a35bd1e3STakashi Iwai 	if (!inv_dmic)
3651a35bd1e3STakashi Iwai 		return 0;
3652352f7f91STakashi Iwai 
3653352f7f91STakashi Iwai 	/* Make independent right kcontrol */
3654352f7f91STakashi Iwai 	if (label)
3655352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3656352f7f91STakashi Iwai 			 "Inverted %s Capture %s", label, sfx);
3657352f7f91STakashi Iwai 	else
3658352f7f91STakashi Iwai 		snprintf(tmpname, sizeof(tmpname),
3659352f7f91STakashi Iwai 			 "Inverted Capture %s", sfx);
3660a35bd1e3STakashi Iwai 	knew = add_control(spec, type, tmpname, idx,
3661352f7f91STakashi Iwai 			   amp_val_replace_channels(ctl, 2));
3662a35bd1e3STakashi Iwai 	if (!knew)
3663a35bd1e3STakashi Iwai 		return -ENOMEM;
3664e65bf997SJaroslav Kysela 	if (is_switch) {
3665a35bd1e3STakashi Iwai 		knew->put = cap_single_sw_put;
3666e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3667e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3668e65bf997SJaroslav Kysela 	}
3669a35bd1e3STakashi Iwai 	return 0;
3670352f7f91STakashi Iwai }
3671352f7f91STakashi Iwai 
3672352f7f91STakashi Iwai /* create single (and simple) capture volume and switch controls */
3673352f7f91STakashi Iwai static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3674352f7f91STakashi Iwai 				     unsigned int vol_ctl, unsigned int sw_ctl,
3675352f7f91STakashi Iwai 				     bool inv_dmic)
3676352f7f91STakashi Iwai {
3677352f7f91STakashi Iwai 	int err;
3678352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3679352f7f91STakashi Iwai 	if (err < 0)
3680352f7f91STakashi Iwai 		return err;
3681352f7f91STakashi Iwai 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3682071c73adSTakashi Iwai 	if (err < 0)
3683071c73adSTakashi Iwai 		return err;
3684071c73adSTakashi Iwai 	return 0;
36851da177e4SLinus Torvalds }
3686071c73adSTakashi Iwai 
3687352f7f91STakashi Iwai /* create bound capture volume and switch controls */
3688352f7f91STakashi Iwai static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3689352f7f91STakashi Iwai 				   unsigned int vol_ctl, unsigned int sw_ctl)
3690352f7f91STakashi Iwai {
3691352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3692352f7f91STakashi Iwai 	struct snd_kcontrol_new *knew;
3693352f7f91STakashi Iwai 
3694352f7f91STakashi Iwai 	if (vol_ctl) {
369512c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3696352f7f91STakashi Iwai 		if (!knew)
3697352f7f91STakashi Iwai 			return -ENOMEM;
3698352f7f91STakashi Iwai 		knew->index = idx;
3699352f7f91STakashi Iwai 		knew->private_value = vol_ctl;
3700352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3701352f7f91STakashi Iwai 	}
3702352f7f91STakashi Iwai 	if (sw_ctl) {
370312c93df6STakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3704352f7f91STakashi Iwai 		if (!knew)
3705352f7f91STakashi Iwai 			return -ENOMEM;
3706352f7f91STakashi Iwai 		knew->index = idx;
3707352f7f91STakashi Iwai 		knew->private_value = sw_ctl;
3708352f7f91STakashi Iwai 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3709e65bf997SJaroslav Kysela 		if (spec->mic_mute_led)
3710e65bf997SJaroslav Kysela 			knew->access |= SNDRV_CTL_ELEM_ACCESS_MIC_LED;
3711352f7f91STakashi Iwai 	}
3712352f7f91STakashi Iwai 	return 0;
3713352f7f91STakashi Iwai }
3714352f7f91STakashi Iwai 
3715352f7f91STakashi Iwai /* return the vol ctl when used first in the imux list */
3716352f7f91STakashi Iwai static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3717352f7f91STakashi Iwai {
3718352f7f91STakashi Iwai 	struct nid_path *path;
3719352f7f91STakashi Iwai 	unsigned int ctl;
3720352f7f91STakashi Iwai 	int i;
3721352f7f91STakashi Iwai 
3722c697b716STakashi Iwai 	path = get_input_path(codec, 0, idx);
3723352f7f91STakashi Iwai 	if (!path)
3724352f7f91STakashi Iwai 		return 0;
3725352f7f91STakashi Iwai 	ctl = path->ctls[type];
3726352f7f91STakashi Iwai 	if (!ctl)
3727352f7f91STakashi Iwai 		return 0;
3728352f7f91STakashi Iwai 	for (i = 0; i < idx - 1; i++) {
3729c697b716STakashi Iwai 		path = get_input_path(codec, 0, i);
3730352f7f91STakashi Iwai 		if (path && path->ctls[type] == ctl)
3731352f7f91STakashi Iwai 			return 0;
3732352f7f91STakashi Iwai 	}
3733352f7f91STakashi Iwai 	return ctl;
3734352f7f91STakashi Iwai }
3735352f7f91STakashi Iwai 
3736352f7f91STakashi Iwai /* create individual capture volume and switch controls per input */
3737352f7f91STakashi Iwai static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3738352f7f91STakashi Iwai {
3739352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3740352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3741c970042cSTakashi Iwai 	int i, err, type;
3742352f7f91STakashi Iwai 
3743352f7f91STakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3744352f7f91STakashi Iwai 		bool inv_dmic;
3745c970042cSTakashi Iwai 		int idx;
37469dba205bSTakashi Iwai 
3747c970042cSTakashi Iwai 		idx = imux->items[i].index;
3748c970042cSTakashi Iwai 		if (idx >= spec->autocfg.num_inputs)
37499dba205bSTakashi Iwai 			continue;
3750352f7f91STakashi Iwai 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3751352f7f91STakashi Iwai 
3752352f7f91STakashi Iwai 		for (type = 0; type < 2; type++) {
3753c970042cSTakashi Iwai 			err = add_single_cap_ctl(codec,
3754c970042cSTakashi Iwai 						 spec->input_labels[idx],
3755c970042cSTakashi Iwai 						 spec->input_label_idxs[idx],
3756c970042cSTakashi Iwai 						 type,
3757352f7f91STakashi Iwai 						 get_first_cap_ctl(codec, i, type),
3758352f7f91STakashi Iwai 						 inv_dmic);
3759d13bd412STakashi Iwai 			if (err < 0)
3760071c73adSTakashi Iwai 				return err;
3761352f7f91STakashi Iwai 		}
3762352f7f91STakashi Iwai 	}
3763071c73adSTakashi Iwai 	return 0;
3764352f7f91STakashi Iwai }
3765071c73adSTakashi Iwai 
3766352f7f91STakashi Iwai static int create_capture_mixers(struct hda_codec *codec)
3767352f7f91STakashi Iwai {
3768352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3769352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3770352f7f91STakashi Iwai 	int i, n, nums, err;
3771352f7f91STakashi Iwai 
3772352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
3773352f7f91STakashi Iwai 		nums = 1;
3774352f7f91STakashi Iwai 	else
3775352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
3776352f7f91STakashi Iwai 
3777352f7f91STakashi Iwai 	if (!spec->auto_mic && imux->num_items > 1) {
3778352f7f91STakashi Iwai 		struct snd_kcontrol_new *knew;
3779624d914dSTakashi Iwai 		const char *name;
3780624d914dSTakashi Iwai 		name = nums > 1 ? "Input Source" : "Capture Source";
3781624d914dSTakashi Iwai 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3782352f7f91STakashi Iwai 		if (!knew)
3783352f7f91STakashi Iwai 			return -ENOMEM;
3784352f7f91STakashi Iwai 		knew->count = nums;
3785352f7f91STakashi Iwai 	}
3786352f7f91STakashi Iwai 
3787352f7f91STakashi Iwai 	for (n = 0; n < nums; n++) {
3788352f7f91STakashi Iwai 		bool multi = false;
378999a5592dSDavid Henningsson 		bool multi_cap_vol = spec->multi_cap_vol;
3790352f7f91STakashi Iwai 		bool inv_dmic = false;
3791352f7f91STakashi Iwai 		int vol, sw;
3792352f7f91STakashi Iwai 
3793352f7f91STakashi Iwai 		vol = sw = 0;
3794352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
3795352f7f91STakashi Iwai 			struct nid_path *path;
3796c697b716STakashi Iwai 			path = get_input_path(codec, n, i);
3797352f7f91STakashi Iwai 			if (!path)
3798352f7f91STakashi Iwai 				continue;
3799352f7f91STakashi Iwai 			parse_capvol_in_path(codec, path);
3800352f7f91STakashi Iwai 			if (!vol)
3801352f7f91STakashi Iwai 				vol = path->ctls[NID_PATH_VOL_CTL];
380299a5592dSDavid Henningsson 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3803352f7f91STakashi Iwai 				multi = true;
380499a5592dSDavid Henningsson 				if (!same_amp_caps(codec, vol,
380599a5592dSDavid Henningsson 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
380699a5592dSDavid Henningsson 					multi_cap_vol = true;
380799a5592dSDavid Henningsson 			}
3808352f7f91STakashi Iwai 			if (!sw)
3809352f7f91STakashi Iwai 				sw = path->ctls[NID_PATH_MUTE_CTL];
381099a5592dSDavid Henningsson 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3811352f7f91STakashi Iwai 				multi = true;
381299a5592dSDavid Henningsson 				if (!same_amp_caps(codec, sw,
381399a5592dSDavid Henningsson 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
381499a5592dSDavid Henningsson 					multi_cap_vol = true;
381599a5592dSDavid Henningsson 			}
3816352f7f91STakashi Iwai 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3817352f7f91STakashi Iwai 				inv_dmic = true;
3818352f7f91STakashi Iwai 		}
3819352f7f91STakashi Iwai 
3820352f7f91STakashi Iwai 		if (!multi)
3821352f7f91STakashi Iwai 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3822352f7f91STakashi Iwai 							inv_dmic);
3823ccb04157SDavid Henningsson 		else if (!multi_cap_vol && !inv_dmic)
3824352f7f91STakashi Iwai 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3825352f7f91STakashi Iwai 		else
3826352f7f91STakashi Iwai 			err = create_multi_cap_vol_ctl(codec);
3827d13bd412STakashi Iwai 		if (err < 0)
3828071c73adSTakashi Iwai 			return err;
3829071c73adSTakashi Iwai 	}
3830071c73adSTakashi Iwai 
38311da177e4SLinus Torvalds 	return 0;
38321da177e4SLinus Torvalds }
38331da177e4SLinus Torvalds 
3834352f7f91STakashi Iwai /*
3835352f7f91STakashi Iwai  * add mic boosts if needed
3836352f7f91STakashi Iwai  */
38376f7c83afSTakashi Iwai 
38386f7c83afSTakashi Iwai /* check whether the given amp is feasible as a boost volume */
38396f7c83afSTakashi Iwai static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
38406f7c83afSTakashi Iwai 			    int dir, int idx)
38416f7c83afSTakashi Iwai {
38426f7c83afSTakashi Iwai 	unsigned int step;
38436f7c83afSTakashi Iwai 
38446f7c83afSTakashi Iwai 	if (!nid_has_volume(codec, nid, dir) ||
38456f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
38466f7c83afSTakashi Iwai 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
38476f7c83afSTakashi Iwai 		return false;
38486f7c83afSTakashi Iwai 
38496f7c83afSTakashi Iwai 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
38506f7c83afSTakashi Iwai 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
38516f7c83afSTakashi Iwai 	if (step < 0x20)
38526f7c83afSTakashi Iwai 		return false;
38536f7c83afSTakashi Iwai 	return true;
38546f7c83afSTakashi Iwai }
38556f7c83afSTakashi Iwai 
38566f7c83afSTakashi Iwai /* look for a boost amp in a widget close to the pin */
38576f7c83afSTakashi Iwai static unsigned int look_for_boost_amp(struct hda_codec *codec,
38586f7c83afSTakashi Iwai 				       struct nid_path *path)
38596f7c83afSTakashi Iwai {
38606f7c83afSTakashi Iwai 	unsigned int val = 0;
38616f7c83afSTakashi Iwai 	hda_nid_t nid;
38626f7c83afSTakashi Iwai 	int depth;
38636f7c83afSTakashi Iwai 
38646f7c83afSTakashi Iwai 	for (depth = 0; depth < 3; depth++) {
38656f7c83afSTakashi Iwai 		if (depth >= path->depth - 1)
38666f7c83afSTakashi Iwai 			break;
38676f7c83afSTakashi Iwai 		nid = path->path[depth];
38686f7c83afSTakashi Iwai 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
38696f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
38706f7c83afSTakashi Iwai 			break;
38716f7c83afSTakashi Iwai 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
38726f7c83afSTakashi Iwai 					   path->idx[depth])) {
38736f7c83afSTakashi Iwai 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
38746f7c83afSTakashi Iwai 						  HDA_INPUT);
38756f7c83afSTakashi Iwai 			break;
38766f7c83afSTakashi Iwai 		}
38776f7c83afSTakashi Iwai 	}
38786f7c83afSTakashi Iwai 
38796f7c83afSTakashi Iwai 	return val;
38806f7c83afSTakashi Iwai }
38816f7c83afSTakashi Iwai 
3882352f7f91STakashi Iwai static int parse_mic_boost(struct hda_codec *codec)
3883352f7f91STakashi Iwai {
3884352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
3885352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
38866f7c83afSTakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
3887a35bd1e3STakashi Iwai 	int i;
3888352f7f91STakashi Iwai 
38896f7c83afSTakashi Iwai 	if (!spec->num_adc_nids)
38906f7c83afSTakashi Iwai 		return 0;
38916f7c83afSTakashi Iwai 
38926f7c83afSTakashi Iwai 	for (i = 0; i < imux->num_items; i++) {
3893352f7f91STakashi Iwai 		struct nid_path *path;
3894352f7f91STakashi Iwai 		unsigned int val;
38956f7c83afSTakashi Iwai 		int idx;
3896975cc02aSTakashi Iwai 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3897352f7f91STakashi Iwai 
38986f7c83afSTakashi Iwai 		idx = imux->items[i].index;
38996f7c83afSTakashi Iwai 		if (idx >= imux->num_items)
390002aba550SDavid Henningsson 			continue;
390102aba550SDavid Henningsson 
39026f7c83afSTakashi Iwai 		/* check only line-in and mic pins */
39031799cdd5STakashi Iwai 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
39046f7c83afSTakashi Iwai 			continue;
39056f7c83afSTakashi Iwai 
39066f7c83afSTakashi Iwai 		path = get_input_path(codec, 0, i);
39076f7c83afSTakashi Iwai 		if (!path)
39086f7c83afSTakashi Iwai 			continue;
39096f7c83afSTakashi Iwai 
39106f7c83afSTakashi Iwai 		val = look_for_boost_amp(codec, path);
39116f7c83afSTakashi Iwai 		if (!val)
39126f7c83afSTakashi Iwai 			continue;
39136f7c83afSTakashi Iwai 
39146f7c83afSTakashi Iwai 		/* create a boost control */
3915352f7f91STakashi Iwai 		snprintf(boost_label, sizeof(boost_label),
39166f7c83afSTakashi Iwai 			 "%s Boost Volume", spec->input_labels[idx]);
3917a35bd1e3STakashi Iwai 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3918a35bd1e3STakashi Iwai 				 spec->input_label_idxs[idx], val))
3919a35bd1e3STakashi Iwai 			return -ENOMEM;
3920352f7f91STakashi Iwai 
3921352f7f91STakashi Iwai 		path->ctls[NID_PATH_BOOST_CTL] = val;
3922352f7f91STakashi Iwai 	}
3923352f7f91STakashi Iwai 	return 0;
3924352f7f91STakashi Iwai }
3925352f7f91STakashi Iwai 
39267cdf8c49STakashi Iwai #ifdef CONFIG_SND_HDA_GENERIC_LEDS
3927352f7f91STakashi Iwai /*
392815509b63STakashi Iwai  * vmaster mute LED hook helpers
392915509b63STakashi Iwai  */
393015509b63STakashi Iwai 
393115509b63STakashi Iwai static int create_mute_led_cdev(struct hda_codec *codec,
393215509b63STakashi Iwai 				int (*callback)(struct led_classdev *,
393315509b63STakashi Iwai 						enum led_brightness),
393415509b63STakashi Iwai 				bool micmute)
393515509b63STakashi Iwai {
3936549f8ffcSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
393715509b63STakashi Iwai 	struct led_classdev *cdev;
3938549f8ffcSTakashi Iwai 	int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE;
3939549f8ffcSTakashi Iwai 	int err;
394015509b63STakashi Iwai 
394115509b63STakashi Iwai 	cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
394215509b63STakashi Iwai 	if (!cdev)
394315509b63STakashi Iwai 		return -ENOMEM;
394415509b63STakashi Iwai 
394515509b63STakashi Iwai 	cdev->name = micmute ? "hda::micmute" : "hda::mute";
394615509b63STakashi Iwai 	cdev->max_brightness = 1;
394715509b63STakashi Iwai 	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
394815509b63STakashi Iwai 	cdev->brightness_set_blocking = callback;
3949c9e272f9STakashi Iwai 	cdev->flags = LED_CORE_SUSPENDRESUME;
395015509b63STakashi Iwai 
3951549f8ffcSTakashi Iwai 	err = led_classdev_register(&codec->core.dev, cdev);
3952549f8ffcSTakashi Iwai 	if (err < 0)
3953549f8ffcSTakashi Iwai 		return err;
3954549f8ffcSTakashi Iwai 	spec->led_cdevs[idx] = cdev;
3955549f8ffcSTakashi Iwai 	return 0;
395615509b63STakashi Iwai }
395715509b63STakashi Iwai 
395815509b63STakashi Iwai /**
39593531ba21SPierre-Louis Bossart  * snd_hda_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
396015509b63STakashi Iwai  * @codec: the HDA codec
396115509b63STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
396215509b63STakashi Iwai  */
396315509b63STakashi Iwai int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
396415509b63STakashi Iwai 				  int (*callback)(struct led_classdev *,
396515509b63STakashi Iwai 						  enum led_brightness))
396615509b63STakashi Iwai {
396715509b63STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
396815509b63STakashi Iwai 	int err;
396915509b63STakashi Iwai 
397015509b63STakashi Iwai 	if (callback) {
397115509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, false);
397215509b63STakashi Iwai 		if (err) {
397315509b63STakashi Iwai 			codec_warn(codec, "failed to create a mute LED cdev\n");
397415509b63STakashi Iwai 			return err;
397515509b63STakashi Iwai 		}
397615509b63STakashi Iwai 	}
397715509b63STakashi Iwai 
397815509b63STakashi Iwai 	if (spec->vmaster_mute.hook)
397915509b63STakashi Iwai 		codec_err(codec, "vmaster hook already present before cdev!\n");
398015509b63STakashi Iwai 
3981e65bf997SJaroslav Kysela 	spec->vmaster_mute_led = 1;
398215509b63STakashi Iwai 	return 0;
398315509b63STakashi Iwai }
398415509b63STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
398515509b63STakashi Iwai 
3986b3802783STakashi Iwai /**
39873531ba21SPierre-Louis Bossart  * snd_hda_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
39887cdf8c49STakashi Iwai  * @codec: the HDA codec
39897cdf8c49STakashi Iwai  * @callback: the callback for LED classdev brightness_set_blocking
39907cdf8c49STakashi Iwai  *
39917cdf8c49STakashi Iwai  * Called from the codec drivers for offering the mic mute LED controls.
39927cdf8c49STakashi Iwai  * This creates a LED classdev and sets up the cap_sync_hook that is called at
39937cdf8c49STakashi Iwai  * each time when the capture mixer switch changes.
39947cdf8c49STakashi Iwai  *
39957cdf8c49STakashi Iwai  * When NULL is passed to @callback, no classdev is created but only the
39967cdf8c49STakashi Iwai  * LED-trigger is set up.
39977cdf8c49STakashi Iwai  *
39987cdf8c49STakashi Iwai  * Returns 0 or a negative error.
39997cdf8c49STakashi Iwai  */
40007cdf8c49STakashi Iwai int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
40017cdf8c49STakashi Iwai 				     int (*callback)(struct led_classdev *,
40027cdf8c49STakashi Iwai 						     enum led_brightness))
40037cdf8c49STakashi Iwai {
4004e65bf997SJaroslav Kysela 	struct hda_gen_spec *spec = codec->spec;
40057cdf8c49STakashi Iwai 	int err;
40067cdf8c49STakashi Iwai 
40077cdf8c49STakashi Iwai 	if (callback) {
400815509b63STakashi Iwai 		err = create_mute_led_cdev(codec, callback, true);
40097cdf8c49STakashi Iwai 		if (err) {
40107cdf8c49STakashi Iwai 			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
40117cdf8c49STakashi Iwai 			return err;
40127cdf8c49STakashi Iwai 		}
40137cdf8c49STakashi Iwai 	}
40147cdf8c49STakashi Iwai 
4015e65bf997SJaroslav Kysela 	spec->mic_mute_led = 1;
4016e65bf997SJaroslav Kysela 	return 0;
40177cdf8c49STakashi Iwai }
40187cdf8c49STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
40197cdf8c49STakashi Iwai #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
40207cdf8c49STakashi Iwai 
4021f567b788STakashi Iwai /*
4022352f7f91STakashi Iwai  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
4023352f7f91STakashi Iwai  */
4024352f7f91STakashi Iwai static void parse_digital(struct hda_codec *codec)
4025352f7f91STakashi Iwai {
4026352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
40270c8c0f56STakashi Iwai 	struct nid_path *path;
4028352f7f91STakashi Iwai 	int i, nums;
40292c12c30dSTakashi Iwai 	hda_nid_t dig_nid, pin;
4030352f7f91STakashi Iwai 
40319ab0cb30STakashi Iwai 	/* support multiple SPDIFs; the secondary is set up as a follower */
4032352f7f91STakashi Iwai 	nums = 0;
4033352f7f91STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
40342c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_out_pins[i];
4035352f7f91STakashi Iwai 		dig_nid = look_for_dac(codec, pin, true);
4036352f7f91STakashi Iwai 		if (!dig_nid)
4037352f7f91STakashi Iwai 			continue;
40383ca529d3STakashi Iwai 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
40390c8c0f56STakashi Iwai 		if (!path)
4040352f7f91STakashi Iwai 			continue;
40414e76a883STakashi Iwai 		print_nid_path(codec, "digout", path);
4042e1284af7STakashi Iwai 		path->active = true;
40436b275b14STakashi Iwai 		path->pin_fixed = true; /* no jack detection */
4044196c1766STakashi Iwai 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
40452c12c30dSTakashi Iwai 		set_pin_target(codec, pin, PIN_OUT, false);
4046352f7f91STakashi Iwai 		if (!nums) {
4047352f7f91STakashi Iwai 			spec->multiout.dig_out_nid = dig_nid;
4048352f7f91STakashi Iwai 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
4049352f7f91STakashi Iwai 		} else {
40509ab0cb30STakashi Iwai 			spec->multiout.follower_dig_outs = spec->follower_dig_outs;
40519ab0cb30STakashi Iwai 			if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1)
4052352f7f91STakashi Iwai 				break;
40539ab0cb30STakashi Iwai 			spec->follower_dig_outs[nums - 1] = dig_nid;
4054352f7f91STakashi Iwai 		}
4055352f7f91STakashi Iwai 		nums++;
4056352f7f91STakashi Iwai 	}
4057352f7f91STakashi Iwai 
4058352f7f91STakashi Iwai 	if (spec->autocfg.dig_in_pin) {
40592c12c30dSTakashi Iwai 		pin = spec->autocfg.dig_in_pin;
40607639a06cSTakashi Iwai 		for_each_hda_codec_node(dig_nid, codec) {
4061352f7f91STakashi Iwai 			unsigned int wcaps = get_wcaps(codec, dig_nid);
4062352f7f91STakashi Iwai 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
4063352f7f91STakashi Iwai 				continue;
4064352f7f91STakashi Iwai 			if (!(wcaps & AC_WCAP_DIGITAL))
4065352f7f91STakashi Iwai 				continue;
40662c12c30dSTakashi Iwai 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
4067352f7f91STakashi Iwai 			if (path) {
40684e76a883STakashi Iwai 				print_nid_path(codec, "digin", path);
4069352f7f91STakashi Iwai 				path->active = true;
40706b275b14STakashi Iwai 				path->pin_fixed = true; /* no jack */
4071352f7f91STakashi Iwai 				spec->dig_in_nid = dig_nid;
40722430d7b7STakashi Iwai 				spec->digin_path = snd_hda_get_path_idx(codec, path);
40732c12c30dSTakashi Iwai 				set_pin_target(codec, pin, PIN_IN, false);
4074352f7f91STakashi Iwai 				break;
4075352f7f91STakashi Iwai 			}
4076352f7f91STakashi Iwai 		}
4077352f7f91STakashi Iwai 	}
4078352f7f91STakashi Iwai }
4079352f7f91STakashi Iwai 
40801da177e4SLinus Torvalds 
40811da177e4SLinus Torvalds /*
4082352f7f91STakashi Iwai  * input MUX handling
40831da177e4SLinus Torvalds  */
40841da177e4SLinus Torvalds 
4085352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
4086352f7f91STakashi Iwai 
4087352f7f91STakashi Iwai /* select the given imux item; either unmute exclusively or select the route */
4088352f7f91STakashi Iwai static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
4089352f7f91STakashi Iwai 		      unsigned int idx)
4090352f7f91STakashi Iwai {
4091352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4092352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
409355196fffSTakashi Iwai 	struct nid_path *old_path, *path;
4094352f7f91STakashi Iwai 
4095352f7f91STakashi Iwai 	imux = &spec->input_mux;
4096352f7f91STakashi Iwai 	if (!imux->num_items)
40971da177e4SLinus Torvalds 		return 0;
40981da177e4SLinus Torvalds 
4099352f7f91STakashi Iwai 	if (idx >= imux->num_items)
4100352f7f91STakashi Iwai 		idx = imux->num_items - 1;
4101352f7f91STakashi Iwai 	if (spec->cur_mux[adc_idx] == idx)
4102352f7f91STakashi Iwai 		return 0;
4103352f7f91STakashi Iwai 
410455196fffSTakashi Iwai 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
410555196fffSTakashi Iwai 	if (!old_path)
4106352f7f91STakashi Iwai 		return 0;
410755196fffSTakashi Iwai 	if (old_path->active)
410855196fffSTakashi Iwai 		snd_hda_activate_path(codec, old_path, false, false);
4109352f7f91STakashi Iwai 
4110352f7f91STakashi Iwai 	spec->cur_mux[adc_idx] = idx;
4111352f7f91STakashi Iwai 
4112967303daSTakashi Iwai 	if (spec->hp_mic)
4113967303daSTakashi Iwai 		update_hp_mic(codec, adc_idx, false);
4114352f7f91STakashi Iwai 
4115352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
4116352f7f91STakashi Iwai 		dyn_adc_pcm_resetup(codec, idx);
4117352f7f91STakashi Iwai 
4118c697b716STakashi Iwai 	path = get_input_path(codec, adc_idx, idx);
4119352f7f91STakashi Iwai 	if (!path)
4120352f7f91STakashi Iwai 		return 0;
4121352f7f91STakashi Iwai 	if (path->active)
4122352f7f91STakashi Iwai 		return 0;
4123352f7f91STakashi Iwai 	snd_hda_activate_path(codec, path, true, false);
4124352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
41257fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
412655196fffSTakashi Iwai 	path_power_down_sync(codec, old_path);
41271da177e4SLinus Torvalds 	return 1;
41281da177e4SLinus Torvalds }
41291da177e4SLinus Torvalds 
4130e6feb5d0STakashi Iwai /* power up/down widgets in the all paths that match with the given NID
4131e6feb5d0STakashi Iwai  * as terminals (either start- or endpoint)
4132e6feb5d0STakashi Iwai  *
4133e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4134e6feb5d0STakashi Iwai  */
4135e6feb5d0STakashi Iwai static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
4136e6feb5d0STakashi Iwai 				int pin_state, int stream_state)
4137e6feb5d0STakashi Iwai {
4138e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4139e6feb5d0STakashi Iwai 	hda_nid_t last, changed = 0;
4140e6feb5d0STakashi Iwai 	struct nid_path *path;
4141e6feb5d0STakashi Iwai 	int n;
4142e6feb5d0STakashi Iwai 
4143a9c2dfc8STakashi Iwai 	snd_array_for_each(&spec->paths, n, path) {
414481e43960SBob Copeland 		if (!path->depth)
414581e43960SBob Copeland 			continue;
4146e6feb5d0STakashi Iwai 		if (path->path[0] == nid ||
4147e6feb5d0STakashi Iwai 		    path->path[path->depth - 1] == nid) {
4148e6feb5d0STakashi Iwai 			bool pin_old = path->pin_enabled;
4149e6feb5d0STakashi Iwai 			bool stream_old = path->stream_enabled;
4150e6feb5d0STakashi Iwai 
4151e6feb5d0STakashi Iwai 			if (pin_state >= 0)
4152e6feb5d0STakashi Iwai 				path->pin_enabled = pin_state;
4153e6feb5d0STakashi Iwai 			if (stream_state >= 0)
4154e6feb5d0STakashi Iwai 				path->stream_enabled = stream_state;
41556b275b14STakashi Iwai 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
41566b275b14STakashi Iwai 			    || path->stream_enabled != stream_old) {
4157e6feb5d0STakashi Iwai 				last = path_power_update(codec, path, true);
4158e6feb5d0STakashi Iwai 				if (last)
4159e6feb5d0STakashi Iwai 					changed = last;
4160e6feb5d0STakashi Iwai 			}
4161e6feb5d0STakashi Iwai 		}
4162e6feb5d0STakashi Iwai 	}
4163e6feb5d0STakashi Iwai 	return changed;
4164e6feb5d0STakashi Iwai }
4165e6feb5d0STakashi Iwai 
4166d5ac0100STakashi Iwai /* check the jack status for power control */
4167d5ac0100STakashi Iwai static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4168d5ac0100STakashi Iwai {
4169d5ac0100STakashi Iwai 	if (!is_jack_detectable(codec, pin))
4170d5ac0100STakashi Iwai 		return true;
4171d5ac0100STakashi Iwai 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4172d5ac0100STakashi Iwai }
4173d5ac0100STakashi Iwai 
4174e6feb5d0STakashi Iwai /* power up/down the paths of the given pin according to the jack state;
4175e6feb5d0STakashi Iwai  * power = 0/1 : only power up/down if it matches with the jack state,
4176e6feb5d0STakashi Iwai  *       < 0   : force power up/down to follow the jack sate
4177e6feb5d0STakashi Iwai  *
4178e6feb5d0STakashi Iwai  * returns the last changed NID, or zero if unchanged.
4179e6feb5d0STakashi Iwai  */
4180e6feb5d0STakashi Iwai static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4181e6feb5d0STakashi Iwai 				    int power)
4182e6feb5d0STakashi Iwai {
4183e6feb5d0STakashi Iwai 	bool on;
4184e6feb5d0STakashi Iwai 
4185967b1307STakashi Iwai 	if (!codec->power_save_node)
4186e6feb5d0STakashi Iwai 		return 0;
4187e6feb5d0STakashi Iwai 
4188d5ac0100STakashi Iwai 	on = detect_pin_state(codec, pin);
4189d5ac0100STakashi Iwai 
4190e6feb5d0STakashi Iwai 	if (power >= 0 && on != power)
4191e6feb5d0STakashi Iwai 		return 0;
4192e6feb5d0STakashi Iwai 	return set_path_power(codec, pin, on, -1);
4193e6feb5d0STakashi Iwai }
4194e6feb5d0STakashi Iwai 
4195e6feb5d0STakashi Iwai static void pin_power_callback(struct hda_codec *codec,
4196e6feb5d0STakashi Iwai 			       struct hda_jack_callback *jack,
4197e6feb5d0STakashi Iwai 			       bool on)
4198e6feb5d0STakashi Iwai {
41992ebab40eSTakashi Iwai 	if (jack && jack->nid)
4200e6feb5d0STakashi Iwai 		sync_power_state_change(codec,
42012ebab40eSTakashi Iwai 					set_pin_power_jack(codec, jack->nid, on));
4202e6feb5d0STakashi Iwai }
4203e6feb5d0STakashi Iwai 
4204e6feb5d0STakashi Iwai /* callback only doing power up -- called at first */
4205e6feb5d0STakashi Iwai static void pin_power_up_callback(struct hda_codec *codec,
4206e6feb5d0STakashi Iwai 				  struct hda_jack_callback *jack)
4207e6feb5d0STakashi Iwai {
4208e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, true);
4209e6feb5d0STakashi Iwai }
4210e6feb5d0STakashi Iwai 
4211e6feb5d0STakashi Iwai /* callback only doing power down -- called at last */
4212e6feb5d0STakashi Iwai static void pin_power_down_callback(struct hda_codec *codec,
4213e6feb5d0STakashi Iwai 				    struct hda_jack_callback *jack)
4214e6feb5d0STakashi Iwai {
4215e6feb5d0STakashi Iwai 	pin_power_callback(codec, jack, false);
4216e6feb5d0STakashi Iwai }
4217e6feb5d0STakashi Iwai 
4218e6feb5d0STakashi Iwai /* set up the power up/down callbacks */
4219e6feb5d0STakashi Iwai static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4220e6feb5d0STakashi Iwai 			       const hda_nid_t *pins, bool on)
4221e6feb5d0STakashi Iwai {
4222e6feb5d0STakashi Iwai 	int i;
4223e6feb5d0STakashi Iwai 	hda_jack_callback_fn cb =
4224e6feb5d0STakashi Iwai 		on ? pin_power_up_callback : pin_power_down_callback;
4225e6feb5d0STakashi Iwai 
4226e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++) {
4227e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4228e6feb5d0STakashi Iwai 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4229e6feb5d0STakashi Iwai 		else
4230e6feb5d0STakashi Iwai 			set_path_power(codec, pins[i], true, -1);
4231e6feb5d0STakashi Iwai 	}
4232e6feb5d0STakashi Iwai }
4233e6feb5d0STakashi Iwai 
4234e6feb5d0STakashi Iwai /* enabled power callback to each available I/O pin with jack detections;
4235e6feb5d0STakashi Iwai  * the digital I/O pins are excluded because of the unreliable detectsion
4236e6feb5d0STakashi Iwai  */
4237e6feb5d0STakashi Iwai static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4238e6feb5d0STakashi Iwai {
4239e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4240e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4241e6feb5d0STakashi Iwai 	int i;
4242e6feb5d0STakashi Iwai 
4243967b1307STakashi Iwai 	if (!codec->power_save_node)
4244e6feb5d0STakashi Iwai 		return;
4245e6feb5d0STakashi Iwai 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4246e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4247e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4248e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4249e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4250e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4251e6feb5d0STakashi Iwai 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4252e6feb5d0STakashi Iwai }
4253e6feb5d0STakashi Iwai 
4254e6feb5d0STakashi Iwai /* sync path power up/down with the jack states of given pins */
4255e6feb5d0STakashi Iwai static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4256e6feb5d0STakashi Iwai 				const hda_nid_t *pins)
4257e6feb5d0STakashi Iwai {
4258e6feb5d0STakashi Iwai 	int i;
4259e6feb5d0STakashi Iwai 
4260e6feb5d0STakashi Iwai 	for (i = 0; i < num_pins && pins[i]; i++)
4261e6feb5d0STakashi Iwai 		if (is_jack_detectable(codec, pins[i]))
4262e6feb5d0STakashi Iwai 			set_pin_power_jack(codec, pins[i], -1);
4263e6feb5d0STakashi Iwai }
4264e6feb5d0STakashi Iwai 
4265e6feb5d0STakashi Iwai /* sync path power up/down with pins; called at init and resume */
4266e6feb5d0STakashi Iwai static void sync_all_pin_power_ctls(struct hda_codec *codec)
4267e6feb5d0STakashi Iwai {
4268e6feb5d0STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4269e6feb5d0STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4270e6feb5d0STakashi Iwai 	int i;
4271e6feb5d0STakashi Iwai 
4272967b1307STakashi Iwai 	if (!codec->power_save_node)
4273e6feb5d0STakashi Iwai 		return;
4274e6feb5d0STakashi Iwai 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4275e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4276e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4277e6feb5d0STakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4278e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4279e6feb5d0STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++)
4280e6feb5d0STakashi Iwai 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4281e6feb5d0STakashi Iwai }
42821da177e4SLinus Torvalds 
42835ccf835cSTakashi Iwai /* add fake paths if not present yet */
42845ccf835cSTakashi Iwai static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
42855ccf835cSTakashi Iwai 			   int num_pins, const hda_nid_t *pins)
42865ccf835cSTakashi Iwai {
42875ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
42885ccf835cSTakashi Iwai 	struct nid_path *path;
42895ccf835cSTakashi Iwai 	int i;
42905ccf835cSTakashi Iwai 
42915ccf835cSTakashi Iwai 	for (i = 0; i < num_pins; i++) {
42925ccf835cSTakashi Iwai 		if (!pins[i])
42935ccf835cSTakashi Iwai 			break;
42945ccf835cSTakashi Iwai 		if (get_nid_path(codec, nid, pins[i], 0))
42955ccf835cSTakashi Iwai 			continue;
42965ccf835cSTakashi Iwai 		path = snd_array_new(&spec->paths);
42975ccf835cSTakashi Iwai 		if (!path)
42985ccf835cSTakashi Iwai 			return -ENOMEM;
42995ccf835cSTakashi Iwai 		memset(path, 0, sizeof(*path));
43005ccf835cSTakashi Iwai 		path->depth = 2;
43015ccf835cSTakashi Iwai 		path->path[0] = nid;
43025ccf835cSTakashi Iwai 		path->path[1] = pins[i];
43035ccf835cSTakashi Iwai 		path->active = true;
43045ccf835cSTakashi Iwai 	}
43055ccf835cSTakashi Iwai 	return 0;
43065ccf835cSTakashi Iwai }
43075ccf835cSTakashi Iwai 
43085ccf835cSTakashi Iwai /* create fake paths to all outputs from beep */
43095ccf835cSTakashi Iwai static int add_fake_beep_paths(struct hda_codec *codec)
43105ccf835cSTakashi Iwai {
43115ccf835cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
43125ccf835cSTakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
43135ccf835cSTakashi Iwai 	hda_nid_t nid = spec->beep_nid;
43145ccf835cSTakashi Iwai 	int err;
43155ccf835cSTakashi Iwai 
4316967b1307STakashi Iwai 	if (!codec->power_save_node || !nid)
43175ccf835cSTakashi Iwai 		return 0;
43185ccf835cSTakashi Iwai 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
43195ccf835cSTakashi Iwai 	if (err < 0)
43205ccf835cSTakashi Iwai 		return err;
43215ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
43225ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
43235ccf835cSTakashi Iwai 		if (err < 0)
43245ccf835cSTakashi Iwai 			return err;
43255ccf835cSTakashi Iwai 	}
43265ccf835cSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
43275ccf835cSTakashi Iwai 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
43285ccf835cSTakashi Iwai 				     cfg->speaker_pins);
43295ccf835cSTakashi Iwai 		if (err < 0)
43305ccf835cSTakashi Iwai 			return err;
43315ccf835cSTakashi Iwai 	}
43325ccf835cSTakashi Iwai 	return 0;
43335ccf835cSTakashi Iwai }
43345ccf835cSTakashi Iwai 
43355ccf835cSTakashi Iwai /* power up/down beep widget and its output paths */
43365ccf835cSTakashi Iwai static void beep_power_hook(struct hda_beep *beep, bool on)
43375ccf835cSTakashi Iwai {
43385ccf835cSTakashi Iwai 	set_path_power(beep->codec, beep->nid, -1, on);
43395ccf835cSTakashi Iwai }
43405ccf835cSTakashi Iwai 
43416b275b14STakashi Iwai /**
43426b275b14STakashi Iwai  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
43436b275b14STakashi Iwai  * @codec: the HDA codec
43446b275b14STakashi Iwai  * @pin: NID of pin to fix
43456b275b14STakashi Iwai  */
43466b275b14STakashi Iwai int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
43476b275b14STakashi Iwai {
43486b275b14STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
43496b275b14STakashi Iwai 	struct nid_path *path;
43506b275b14STakashi Iwai 
43516b275b14STakashi Iwai 	path = snd_array_new(&spec->paths);
43526b275b14STakashi Iwai 	if (!path)
43536b275b14STakashi Iwai 		return -ENOMEM;
43546b275b14STakashi Iwai 	memset(path, 0, sizeof(*path));
43556b275b14STakashi Iwai 	path->depth = 1;
43566b275b14STakashi Iwai 	path->path[0] = pin;
43576b275b14STakashi Iwai 	path->active = true;
43586b275b14STakashi Iwai 	path->pin_fixed = true;
43596b275b14STakashi Iwai 	path->stream_enabled = true;
43606b275b14STakashi Iwai 	return 0;
43616b275b14STakashi Iwai }
43626b275b14STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
43636b275b14STakashi Iwai 
43641da177e4SLinus Torvalds /*
4365352f7f91STakashi Iwai  * Jack detections for HP auto-mute and mic-switch
43661da177e4SLinus Torvalds  */
4367352f7f91STakashi Iwai 
4368352f7f91STakashi Iwai /* check each pin in the given array; returns true if any of them is plugged */
4369caf3c043SMichał Mirosław static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
43701da177e4SLinus Torvalds {
437160ea8ca2STakashi Iwai 	int i;
437260ea8ca2STakashi Iwai 	bool present = false;
43731da177e4SLinus Torvalds 
4374352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4375352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4376352f7f91STakashi Iwai 		if (!nid)
4377352f7f91STakashi Iwai 			break;
43780b4df931STakashi Iwai 		/* don't detect pins retasked as inputs */
43790b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
43800b4df931STakashi Iwai 			continue;
438160ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
438260ea8ca2STakashi Iwai 			present = true;
43831da177e4SLinus Torvalds 	}
4384352f7f91STakashi Iwai 	return present;
43851da177e4SLinus Torvalds }
43861da177e4SLinus Torvalds 
4387352f7f91STakashi Iwai /* standard HP/line-out auto-mute helper */
4388caf3c043SMichał Mirosław static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
4389e80c60f3STakashi Iwai 			int *paths, bool mute)
43901da177e4SLinus Torvalds {
4391352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4392352f7f91STakashi Iwai 	int i;
43931da177e4SLinus Torvalds 
4394352f7f91STakashi Iwai 	for (i = 0; i < num_pins; i++) {
4395352f7f91STakashi Iwai 		hda_nid_t nid = pins[i];
4396967303daSTakashi Iwai 		unsigned int val, oldval;
4397352f7f91STakashi Iwai 		if (!nid)
4398352f7f91STakashi Iwai 			break;
43997eebffd3STakashi Iwai 
4400e6feb5d0STakashi Iwai 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4401e6feb5d0STakashi Iwai 		if (oldval & PIN_IN)
4402e6feb5d0STakashi Iwai 			continue; /* no mute for inputs */
4403e6feb5d0STakashi Iwai 
44047eebffd3STakashi Iwai 		if (spec->auto_mute_via_amp) {
4405e80c60f3STakashi Iwai 			struct nid_path *path;
4406e80c60f3STakashi Iwai 			hda_nid_t mute_nid;
4407e80c60f3STakashi Iwai 
4408e80c60f3STakashi Iwai 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4409e80c60f3STakashi Iwai 			if (!path)
4410e80c60f3STakashi Iwai 				continue;
4411e80c60f3STakashi Iwai 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4412e80c60f3STakashi Iwai 			if (!mute_nid)
4413e80c60f3STakashi Iwai 				continue;
44147eebffd3STakashi Iwai 			if (mute)
4415e80c60f3STakashi Iwai 				spec->mute_bits |= (1ULL << mute_nid);
44167eebffd3STakashi Iwai 			else
4417e80c60f3STakashi Iwai 				spec->mute_bits &= ~(1ULL << mute_nid);
44187eebffd3STakashi Iwai 			continue;
4419e6feb5d0STakashi Iwai 		} else {
4420352f7f91STakashi Iwai 			/* don't reset VREF value in case it's controlling
4421352f7f91STakashi Iwai 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4422352f7f91STakashi Iwai 			 */
44232c12c30dSTakashi Iwai 			if (spec->keep_vref_in_automute)
4424967303daSTakashi Iwai 				val = oldval & ~PIN_HP;
44252c12c30dSTakashi Iwai 			else
4426352f7f91STakashi Iwai 				val = 0;
44272c12c30dSTakashi Iwai 			if (!mute)
4428967303daSTakashi Iwai 				val |= oldval;
4429e6feb5d0STakashi Iwai 			/* here we call update_pin_ctl() so that the pinctl is
4430e6feb5d0STakashi Iwai 			 * changed without changing the pinctl target value;
4431e6feb5d0STakashi Iwai 			 * the original target value will be still referred at
4432e6feb5d0STakashi Iwai 			 * the init / resume again
44332c12c30dSTakashi Iwai 			 */
44342c12c30dSTakashi Iwai 			update_pin_ctl(codec, nid, val);
4435e6feb5d0STakashi Iwai 		}
4436e6feb5d0STakashi Iwai 
4437d5a9f1bbSTakashi Iwai 		set_pin_eapd(codec, nid, !mute);
4438967b1307STakashi Iwai 		if (codec->power_save_node) {
4439e6feb5d0STakashi Iwai 			bool on = !mute;
4440e6feb5d0STakashi Iwai 			if (on)
4441d5ac0100STakashi Iwai 				on = detect_pin_state(codec, nid);
4442e6feb5d0STakashi Iwai 			set_path_power(codec, nid, on, -1);
4443e6feb5d0STakashi Iwai 		}
4444352f7f91STakashi Iwai 	}
4445352f7f91STakashi Iwai }
44461da177e4SLinus Torvalds 
4447dda42bd0STakashi Iwai /**
4448dda42bd0STakashi Iwai  * snd_hda_gen_update_outputs - Toggle outputs muting
4449dda42bd0STakashi Iwai  * @codec: the HDA codec
4450dda42bd0STakashi Iwai  *
4451dda42bd0STakashi Iwai  * Update the mute status of all outputs based on the current jack states.
4452dda42bd0STakashi Iwai  */
44535d550e15STakashi Iwai void snd_hda_gen_update_outputs(struct hda_codec *codec)
4454352f7f91STakashi Iwai {
4455352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4456e80c60f3STakashi Iwai 	int *paths;
4457352f7f91STakashi Iwai 	int on;
4458352f7f91STakashi Iwai 
4459352f7f91STakashi Iwai 	/* Control HP pins/amps depending on master_mute state;
4460352f7f91STakashi Iwai 	 * in general, HP pins/amps control should be enabled in all cases,
4461352f7f91STakashi Iwai 	 * but currently set only for master_mute, just to be safe
4462352f7f91STakashi Iwai 	 */
4463e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4464e80c60f3STakashi Iwai 		paths = spec->out_paths;
4465e80c60f3STakashi Iwai 	else
4466e80c60f3STakashi Iwai 		paths = spec->hp_paths;
4467352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4468e80c60f3STakashi Iwai 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4469352f7f91STakashi Iwai 
4470352f7f91STakashi Iwai 	if (!spec->automute_speaker)
4471352f7f91STakashi Iwai 		on = 0;
4472352f7f91STakashi Iwai 	else
4473352f7f91STakashi Iwai 		on = spec->hp_jack_present | spec->line_jack_present;
4474352f7f91STakashi Iwai 	on |= spec->master_mute;
447547b9ddb8STakashi Iwai 	spec->speaker_muted = on;
4476e80c60f3STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4477e80c60f3STakashi Iwai 		paths = spec->out_paths;
4478e80c60f3STakashi Iwai 	else
4479e80c60f3STakashi Iwai 		paths = spec->speaker_paths;
4480352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4481e80c60f3STakashi Iwai 		    spec->autocfg.speaker_pins, paths, on);
4482352f7f91STakashi Iwai 
4483352f7f91STakashi Iwai 	/* toggle line-out mutes if needed, too */
4484352f7f91STakashi Iwai 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4485352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4486352f7f91STakashi Iwai 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4487352f7f91STakashi Iwai 		return;
4488352f7f91STakashi Iwai 	if (!spec->automute_lo)
4489352f7f91STakashi Iwai 		on = 0;
4490352f7f91STakashi Iwai 	else
4491352f7f91STakashi Iwai 		on = spec->hp_jack_present;
4492352f7f91STakashi Iwai 	on |= spec->master_mute;
449347b9ddb8STakashi Iwai 	spec->line_out_muted = on;
4494e80c60f3STakashi Iwai 	paths = spec->out_paths;
4495352f7f91STakashi Iwai 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4496e80c60f3STakashi Iwai 		    spec->autocfg.line_out_pins, paths, on);
4497352f7f91STakashi Iwai }
44982698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4499352f7f91STakashi Iwai 
4500352f7f91STakashi Iwai static void call_update_outputs(struct hda_codec *codec)
4501352f7f91STakashi Iwai {
4502352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4503352f7f91STakashi Iwai 	if (spec->automute_hook)
4504352f7f91STakashi Iwai 		spec->automute_hook(codec);
4505352f7f91STakashi Iwai 	else
45065d550e15STakashi Iwai 		snd_hda_gen_update_outputs(codec);
45077eebffd3STakashi Iwai 
45089ab0cb30STakashi Iwai 	/* sync the whole vmaster followers to reflect the new auto-mute status */
45097eebffd3STakashi Iwai 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
45107eebffd3STakashi Iwai 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4511352f7f91STakashi Iwai }
4512352f7f91STakashi Iwai 
4513dda42bd0STakashi Iwai /**
4514dda42bd0STakashi Iwai  * snd_hda_gen_hp_automute - standard HP-automute helper
4515dda42bd0STakashi Iwai  * @codec: the HDA codec
4516dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4517dda42bd0STakashi Iwai  */
45181a4f69d5STakashi Iwai void snd_hda_gen_hp_automute(struct hda_codec *codec,
45191a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
4520352f7f91STakashi Iwai {
4521352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
452292603c59STakashi Iwai 	hda_nid_t *pins = spec->autocfg.hp_pins;
452392603c59STakashi Iwai 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4524352f7f91STakashi Iwai 
452592603c59STakashi Iwai 	/* No detection for the first HP jack during indep-HP mode */
452692603c59STakashi Iwai 	if (spec->indep_hp_enabled) {
452792603c59STakashi Iwai 		pins++;
452892603c59STakashi Iwai 		num_pins--;
452992603c59STakashi Iwai 	}
453092603c59STakashi Iwai 
453192603c59STakashi Iwai 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4532352f7f91STakashi Iwai 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4533352f7f91STakashi Iwai 		return;
4534352f7f91STakashi Iwai 	call_update_outputs(codec);
4535352f7f91STakashi Iwai }
45362698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4537352f7f91STakashi Iwai 
4538dda42bd0STakashi Iwai /**
4539dda42bd0STakashi Iwai  * snd_hda_gen_line_automute - standard line-out-automute helper
4540dda42bd0STakashi Iwai  * @codec: the HDA codec
4541dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4542dda42bd0STakashi Iwai  */
45431a4f69d5STakashi Iwai void snd_hda_gen_line_automute(struct hda_codec *codec,
45441a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
4545352f7f91STakashi Iwai {
4546352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4547352f7f91STakashi Iwai 
4548352f7f91STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4549352f7f91STakashi Iwai 		return;
4550352f7f91STakashi Iwai 	/* check LO jack only when it's different from HP */
4551352f7f91STakashi Iwai 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4552352f7f91STakashi Iwai 		return;
4553352f7f91STakashi Iwai 
4554352f7f91STakashi Iwai 	spec->line_jack_present =
4555352f7f91STakashi Iwai 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4556352f7f91STakashi Iwai 			     spec->autocfg.line_out_pins);
4557352f7f91STakashi Iwai 	if (!spec->automute_speaker || !spec->detect_lo)
4558352f7f91STakashi Iwai 		return;
4559352f7f91STakashi Iwai 	call_update_outputs(codec);
4560352f7f91STakashi Iwai }
45612698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4562352f7f91STakashi Iwai 
4563dda42bd0STakashi Iwai /**
4564dda42bd0STakashi Iwai  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4565dda42bd0STakashi Iwai  * @codec: the HDA codec
4566dda42bd0STakashi Iwai  * @jack: jack object, NULL for the whole
4567dda42bd0STakashi Iwai  */
45681a4f69d5STakashi Iwai void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
45691a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
4570352f7f91STakashi Iwai {
4571352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4572352f7f91STakashi Iwai 	int i;
4573352f7f91STakashi Iwai 
4574352f7f91STakashi Iwai 	if (!spec->auto_mic)
4575352f7f91STakashi Iwai 		return;
4576352f7f91STakashi Iwai 
4577352f7f91STakashi Iwai 	for (i = spec->am_num_entries - 1; i > 0; i--) {
45780b4df931STakashi Iwai 		hda_nid_t pin = spec->am_entry[i].pin;
45790b4df931STakashi Iwai 		/* don't detect pins retasked as outputs */
45800b4df931STakashi Iwai 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
45810b4df931STakashi Iwai 			continue;
458260ea8ca2STakashi Iwai 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4583352f7f91STakashi Iwai 			mux_select(codec, 0, spec->am_entry[i].idx);
4584352f7f91STakashi Iwai 			return;
4585352f7f91STakashi Iwai 		}
4586352f7f91STakashi Iwai 	}
4587352f7f91STakashi Iwai 	mux_select(codec, 0, spec->am_entry[0].idx);
45881da177e4SLinus Torvalds }
45892698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
45901da177e4SLinus Torvalds 
459177afe0e9STakashi Iwai /* call appropriate hooks */
45921a4f69d5STakashi Iwai static void call_hp_automute(struct hda_codec *codec,
45931a4f69d5STakashi Iwai 			     struct hda_jack_callback *jack)
459477afe0e9STakashi Iwai {
459577afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
459677afe0e9STakashi Iwai 	if (spec->hp_automute_hook)
459777afe0e9STakashi Iwai 		spec->hp_automute_hook(codec, jack);
459877afe0e9STakashi Iwai 	else
459977afe0e9STakashi Iwai 		snd_hda_gen_hp_automute(codec, jack);
460077afe0e9STakashi Iwai }
460177afe0e9STakashi Iwai 
460277afe0e9STakashi Iwai static void call_line_automute(struct hda_codec *codec,
46031a4f69d5STakashi Iwai 			       struct hda_jack_callback *jack)
460477afe0e9STakashi Iwai {
460577afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
460677afe0e9STakashi Iwai 	if (spec->line_automute_hook)
460777afe0e9STakashi Iwai 		spec->line_automute_hook(codec, jack);
460877afe0e9STakashi Iwai 	else
460977afe0e9STakashi Iwai 		snd_hda_gen_line_automute(codec, jack);
461077afe0e9STakashi Iwai }
461177afe0e9STakashi Iwai 
461277afe0e9STakashi Iwai static void call_mic_autoswitch(struct hda_codec *codec,
46131a4f69d5STakashi Iwai 				struct hda_jack_callback *jack)
461477afe0e9STakashi Iwai {
461577afe0e9STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
461677afe0e9STakashi Iwai 	if (spec->mic_autoswitch_hook)
461777afe0e9STakashi Iwai 		spec->mic_autoswitch_hook(codec, jack);
461877afe0e9STakashi Iwai 	else
461977afe0e9STakashi Iwai 		snd_hda_gen_mic_autoswitch(codec, jack);
462077afe0e9STakashi Iwai }
462177afe0e9STakashi Iwai 
4622963afde9STakashi Iwai /* update jack retasking */
4623963afde9STakashi Iwai static void update_automute_all(struct hda_codec *codec)
4624963afde9STakashi Iwai {
4625963afde9STakashi Iwai 	call_hp_automute(codec, NULL);
4626963afde9STakashi Iwai 	call_line_automute(codec, NULL);
4627963afde9STakashi Iwai 	call_mic_autoswitch(codec, NULL);
4628963afde9STakashi Iwai }
4629963afde9STakashi Iwai 
46301da177e4SLinus Torvalds /*
4631352f7f91STakashi Iwai  * Auto-Mute mode mixer enum support
46321da177e4SLinus Torvalds  */
4633352f7f91STakashi Iwai static int automute_mode_info(struct snd_kcontrol *kcontrol,
4634352f7f91STakashi Iwai 			      struct snd_ctl_elem_info *uinfo)
4635352f7f91STakashi Iwai {
4636352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4637352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4638352f7f91STakashi Iwai 	static const char * const texts3[] = {
4639352f7f91STakashi Iwai 		"Disabled", "Speaker Only", "Line Out+Speaker"
46401da177e4SLinus Torvalds 	};
46411da177e4SLinus Torvalds 
4642352f7f91STakashi Iwai 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4643352f7f91STakashi Iwai 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4644352f7f91STakashi Iwai 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4645352f7f91STakashi Iwai }
4646352f7f91STakashi Iwai 
4647352f7f91STakashi Iwai static int automute_mode_get(struct snd_kcontrol *kcontrol,
4648352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4649352f7f91STakashi Iwai {
4650352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4651352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4652352f7f91STakashi Iwai 	unsigned int val = 0;
4653352f7f91STakashi Iwai 	if (spec->automute_speaker)
4654352f7f91STakashi Iwai 		val++;
4655352f7f91STakashi Iwai 	if (spec->automute_lo)
4656352f7f91STakashi Iwai 		val++;
4657352f7f91STakashi Iwai 
4658352f7f91STakashi Iwai 	ucontrol->value.enumerated.item[0] = val;
4659352f7f91STakashi Iwai 	return 0;
4660352f7f91STakashi Iwai }
4661352f7f91STakashi Iwai 
4662352f7f91STakashi Iwai static int automute_mode_put(struct snd_kcontrol *kcontrol,
4663352f7f91STakashi Iwai 			     struct snd_ctl_elem_value *ucontrol)
4664352f7f91STakashi Iwai {
4665352f7f91STakashi Iwai 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4666352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4667352f7f91STakashi Iwai 
4668352f7f91STakashi Iwai 	switch (ucontrol->value.enumerated.item[0]) {
4669352f7f91STakashi Iwai 	case 0:
4670352f7f91STakashi Iwai 		if (!spec->automute_speaker && !spec->automute_lo)
4671352f7f91STakashi Iwai 			return 0;
4672352f7f91STakashi Iwai 		spec->automute_speaker = 0;
4673352f7f91STakashi Iwai 		spec->automute_lo = 0;
4674352f7f91STakashi Iwai 		break;
4675352f7f91STakashi Iwai 	case 1:
4676352f7f91STakashi Iwai 		if (spec->automute_speaker_possible) {
4677352f7f91STakashi Iwai 			if (!spec->automute_lo && spec->automute_speaker)
4678352f7f91STakashi Iwai 				return 0;
4679352f7f91STakashi Iwai 			spec->automute_speaker = 1;
4680352f7f91STakashi Iwai 			spec->automute_lo = 0;
4681352f7f91STakashi Iwai 		} else if (spec->automute_lo_possible) {
4682352f7f91STakashi Iwai 			if (spec->automute_lo)
4683352f7f91STakashi Iwai 				return 0;
4684352f7f91STakashi Iwai 			spec->automute_lo = 1;
4685352f7f91STakashi Iwai 		} else
4686352f7f91STakashi Iwai 			return -EINVAL;
4687352f7f91STakashi Iwai 		break;
4688352f7f91STakashi Iwai 	case 2:
4689352f7f91STakashi Iwai 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4690352f7f91STakashi Iwai 			return -EINVAL;
4691352f7f91STakashi Iwai 		if (spec->automute_speaker && spec->automute_lo)
4692352f7f91STakashi Iwai 			return 0;
4693352f7f91STakashi Iwai 		spec->automute_speaker = 1;
4694352f7f91STakashi Iwai 		spec->automute_lo = 1;
4695352f7f91STakashi Iwai 		break;
4696352f7f91STakashi Iwai 	default:
4697352f7f91STakashi Iwai 		return -EINVAL;
4698352f7f91STakashi Iwai 	}
4699352f7f91STakashi Iwai 	call_update_outputs(codec);
4700352f7f91STakashi Iwai 	return 1;
4701352f7f91STakashi Iwai }
4702352f7f91STakashi Iwai 
4703352f7f91STakashi Iwai static const struct snd_kcontrol_new automute_mode_enum = {
4704352f7f91STakashi Iwai 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4705352f7f91STakashi Iwai 	.name = "Auto-Mute Mode",
4706352f7f91STakashi Iwai 	.info = automute_mode_info,
4707352f7f91STakashi Iwai 	.get = automute_mode_get,
4708352f7f91STakashi Iwai 	.put = automute_mode_put,
4709352f7f91STakashi Iwai };
4710352f7f91STakashi Iwai 
4711352f7f91STakashi Iwai static int add_automute_mode_enum(struct hda_codec *codec)
4712352f7f91STakashi Iwai {
4713352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4714352f7f91STakashi Iwai 
471512c93df6STakashi Iwai 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4716352f7f91STakashi Iwai 		return -ENOMEM;
4717352f7f91STakashi Iwai 	return 0;
4718352f7f91STakashi Iwai }
4719352f7f91STakashi Iwai 
4720352f7f91STakashi Iwai /*
4721352f7f91STakashi Iwai  * Check the availability of HP/line-out auto-mute;
4722352f7f91STakashi Iwai  * Set up appropriately if really supported
4723352f7f91STakashi Iwai  */
4724352f7f91STakashi Iwai static int check_auto_mute_availability(struct hda_codec *codec)
4725352f7f91STakashi Iwai {
4726352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4727352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4728352f7f91STakashi Iwai 	int present = 0;
4729352f7f91STakashi Iwai 	int i, err;
4730352f7f91STakashi Iwai 
4731f72706beSTakashi Iwai 	if (spec->suppress_auto_mute)
4732f72706beSTakashi Iwai 		return 0;
4733f72706beSTakashi Iwai 
4734352f7f91STakashi Iwai 	if (cfg->hp_pins[0])
4735352f7f91STakashi Iwai 		present++;
4736352f7f91STakashi Iwai 	if (cfg->line_out_pins[0])
4737352f7f91STakashi Iwai 		present++;
4738352f7f91STakashi Iwai 	if (cfg->speaker_pins[0])
4739352f7f91STakashi Iwai 		present++;
4740352f7f91STakashi Iwai 	if (present < 2) /* need two different output types */
4741352f7f91STakashi Iwai 		return 0;
4742352f7f91STakashi Iwai 
4743352f7f91STakashi Iwai 	if (!cfg->speaker_pins[0] &&
4744352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4745352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4746352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
4747352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
4748352f7f91STakashi Iwai 	}
4749352f7f91STakashi Iwai 
4750352f7f91STakashi Iwai 	if (!cfg->hp_pins[0] &&
4751352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4752352f7f91STakashi Iwai 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4753352f7f91STakashi Iwai 		       sizeof(cfg->hp_pins));
4754352f7f91STakashi Iwai 		cfg->hp_outs = cfg->line_outs;
4755352f7f91STakashi Iwai 	}
4756352f7f91STakashi Iwai 
4757352f7f91STakashi Iwai 	for (i = 0; i < cfg->hp_outs; i++) {
4758352f7f91STakashi Iwai 		hda_nid_t nid = cfg->hp_pins[i];
4759352f7f91STakashi Iwai 		if (!is_jack_detectable(codec, nid))
4760352f7f91STakashi Iwai 			continue;
47614e76a883STakashi Iwai 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
476262f949bfSTakashi Iwai 		snd_hda_jack_detect_enable_callback(codec, nid,
476377afe0e9STakashi Iwai 						    call_hp_automute);
4764352f7f91STakashi Iwai 		spec->detect_hp = 1;
4765352f7f91STakashi Iwai 	}
4766352f7f91STakashi Iwai 
4767352f7f91STakashi Iwai 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4768352f7f91STakashi Iwai 		if (cfg->speaker_outs)
4769352f7f91STakashi Iwai 			for (i = 0; i < cfg->line_outs; i++) {
4770352f7f91STakashi Iwai 				hda_nid_t nid = cfg->line_out_pins[i];
4771352f7f91STakashi Iwai 				if (!is_jack_detectable(codec, nid))
4772352f7f91STakashi Iwai 					continue;
47734e76a883STakashi Iwai 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4774352f7f91STakashi Iwai 				snd_hda_jack_detect_enable_callback(codec, nid,
477577afe0e9STakashi Iwai 								    call_line_automute);
4776352f7f91STakashi Iwai 				spec->detect_lo = 1;
4777352f7f91STakashi Iwai 			}
4778352f7f91STakashi Iwai 		spec->automute_lo_possible = spec->detect_hp;
4779352f7f91STakashi Iwai 	}
4780352f7f91STakashi Iwai 
4781352f7f91STakashi Iwai 	spec->automute_speaker_possible = cfg->speaker_outs &&
4782352f7f91STakashi Iwai 		(spec->detect_hp || spec->detect_lo);
4783352f7f91STakashi Iwai 
4784352f7f91STakashi Iwai 	spec->automute_lo = spec->automute_lo_possible;
4785352f7f91STakashi Iwai 	spec->automute_speaker = spec->automute_speaker_possible;
4786352f7f91STakashi Iwai 
4787352f7f91STakashi Iwai 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4788352f7f91STakashi Iwai 		/* create a control for automute mode */
4789352f7f91STakashi Iwai 		err = add_automute_mode_enum(codec);
4790352f7f91STakashi Iwai 		if (err < 0)
4791352f7f91STakashi Iwai 			return err;
4792352f7f91STakashi Iwai 	}
4793352f7f91STakashi Iwai 	return 0;
4794352f7f91STakashi Iwai }
4795352f7f91STakashi Iwai 
4796352f7f91STakashi Iwai /* check whether all auto-mic pins are valid; setup indices if OK */
4797352f7f91STakashi Iwai static bool auto_mic_check_imux(struct hda_codec *codec)
4798352f7f91STakashi Iwai {
4799352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4800352f7f91STakashi Iwai 	const struct hda_input_mux *imux;
4801352f7f91STakashi Iwai 	int i;
4802352f7f91STakashi Iwai 
4803352f7f91STakashi Iwai 	imux = &spec->input_mux;
4804352f7f91STakashi Iwai 	for (i = 0; i < spec->am_num_entries; i++) {
4805352f7f91STakashi Iwai 		spec->am_entry[i].idx =
4806352f7f91STakashi Iwai 			find_idx_in_nid_list(spec->am_entry[i].pin,
4807352f7f91STakashi Iwai 					     spec->imux_pins, imux->num_items);
4808352f7f91STakashi Iwai 		if (spec->am_entry[i].idx < 0)
4809352f7f91STakashi Iwai 			return false; /* no corresponding imux */
4810352f7f91STakashi Iwai 	}
4811352f7f91STakashi Iwai 
4812352f7f91STakashi Iwai 	/* we don't need the jack detection for the first pin */
4813352f7f91STakashi Iwai 	for (i = 1; i < spec->am_num_entries; i++)
4814352f7f91STakashi Iwai 		snd_hda_jack_detect_enable_callback(codec,
4815352f7f91STakashi Iwai 						    spec->am_entry[i].pin,
481677afe0e9STakashi Iwai 						    call_mic_autoswitch);
4817352f7f91STakashi Iwai 	return true;
4818352f7f91STakashi Iwai }
4819352f7f91STakashi Iwai 
4820352f7f91STakashi Iwai static int compare_attr(const void *ap, const void *bp)
4821352f7f91STakashi Iwai {
4822352f7f91STakashi Iwai 	const struct automic_entry *a = ap;
4823352f7f91STakashi Iwai 	const struct automic_entry *b = bp;
4824352f7f91STakashi Iwai 	return (int)(a->attr - b->attr);
4825352f7f91STakashi Iwai }
4826352f7f91STakashi Iwai 
4827352f7f91STakashi Iwai /*
4828352f7f91STakashi Iwai  * Check the availability of auto-mic switch;
4829352f7f91STakashi Iwai  * Set up if really supported
4830352f7f91STakashi Iwai  */
4831352f7f91STakashi Iwai static int check_auto_mic_availability(struct hda_codec *codec)
4832352f7f91STakashi Iwai {
4833352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4834352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
4835352f7f91STakashi Iwai 	unsigned int types;
4836352f7f91STakashi Iwai 	int i, num_pins;
4837352f7f91STakashi Iwai 
4838d12daf6fSTakashi Iwai 	if (spec->suppress_auto_mic)
4839d12daf6fSTakashi Iwai 		return 0;
4840d12daf6fSTakashi Iwai 
4841352f7f91STakashi Iwai 	types = 0;
4842352f7f91STakashi Iwai 	num_pins = 0;
4843352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
4844352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
4845352f7f91STakashi Iwai 		unsigned int attr;
4846352f7f91STakashi Iwai 		attr = snd_hda_codec_get_pincfg(codec, nid);
4847352f7f91STakashi Iwai 		attr = snd_hda_get_input_pin_attr(attr);
4848352f7f91STakashi Iwai 		if (types & (1 << attr))
4849352f7f91STakashi Iwai 			return 0; /* already occupied */
4850352f7f91STakashi Iwai 		switch (attr) {
4851352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_INT:
4852352f7f91STakashi Iwai 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4853352f7f91STakashi Iwai 				return 0; /* invalid type */
4854352f7f91STakashi Iwai 			break;
4855352f7f91STakashi Iwai 		case INPUT_PIN_ATTR_UNUSED:
4856352f7f91STakashi Iwai 			return 0; /* invalid entry */
4857352f7f91STakashi Iwai 		default:
4858352f7f91STakashi Iwai 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4859352f7f91STakashi Iwai 				return 0; /* invalid type */
4860352f7f91STakashi Iwai 			if (!spec->line_in_auto_switch &&
4861352f7f91STakashi Iwai 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4862352f7f91STakashi Iwai 				return 0; /* only mic is allowed */
4863352f7f91STakashi Iwai 			if (!is_jack_detectable(codec, nid))
4864352f7f91STakashi Iwai 				return 0; /* no unsol support */
4865352f7f91STakashi Iwai 			break;
4866352f7f91STakashi Iwai 		}
4867352f7f91STakashi Iwai 		if (num_pins >= MAX_AUTO_MIC_PINS)
4868352f7f91STakashi Iwai 			return 0;
4869352f7f91STakashi Iwai 		types |= (1 << attr);
4870352f7f91STakashi Iwai 		spec->am_entry[num_pins].pin = nid;
4871352f7f91STakashi Iwai 		spec->am_entry[num_pins].attr = attr;
4872352f7f91STakashi Iwai 		num_pins++;
4873352f7f91STakashi Iwai 	}
4874352f7f91STakashi Iwai 
4875352f7f91STakashi Iwai 	if (num_pins < 2)
4876352f7f91STakashi Iwai 		return 0;
4877352f7f91STakashi Iwai 
4878352f7f91STakashi Iwai 	spec->am_num_entries = num_pins;
4879352f7f91STakashi Iwai 	/* sort the am_entry in the order of attr so that the pin with a
4880352f7f91STakashi Iwai 	 * higher attr will be selected when the jack is plugged.
4881352f7f91STakashi Iwai 	 */
4882352f7f91STakashi Iwai 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4883352f7f91STakashi Iwai 	     compare_attr, NULL);
4884352f7f91STakashi Iwai 
4885352f7f91STakashi Iwai 	if (!auto_mic_check_imux(codec))
4886352f7f91STakashi Iwai 		return 0;
4887352f7f91STakashi Iwai 
4888352f7f91STakashi Iwai 	spec->auto_mic = 1;
4889352f7f91STakashi Iwai 	spec->num_adc_nids = 1;
4890352f7f91STakashi Iwai 	spec->cur_mux[0] = spec->am_entry[0].idx;
48914e76a883STakashi Iwai 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
4892352f7f91STakashi Iwai 		    spec->am_entry[0].pin,
4893352f7f91STakashi Iwai 		    spec->am_entry[1].pin,
4894352f7f91STakashi Iwai 		    spec->am_entry[2].pin);
4895352f7f91STakashi Iwai 
4896352f7f91STakashi Iwai 	return 0;
4897352f7f91STakashi Iwai }
4898352f7f91STakashi Iwai 
4899dda42bd0STakashi Iwai /**
4900dda42bd0STakashi Iwai  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
4901dda42bd0STakashi Iwai  * into power down
4902dda42bd0STakashi Iwai  * @codec: the HDA codec
4903dda42bd0STakashi Iwai  * @nid: NID to evalute
4904dda42bd0STakashi Iwai  * @power_state: target power state
4905dda42bd0STakashi Iwai  */
4906dfc6e469STakashi Iwai unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
490755196fffSTakashi Iwai 						  hda_nid_t nid,
490855196fffSTakashi Iwai 						  unsigned int power_state)
490955196fffSTakashi Iwai {
4910b6c09b3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
4911b6c09b3cSTakashi Iwai 
4912b6c09b3cSTakashi Iwai 	if (!spec->power_down_unused && !codec->power_save_node)
4913b6c09b3cSTakashi Iwai 		return power_state;
49147639a06cSTakashi Iwai 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
491555196fffSTakashi Iwai 		return power_state;
491655196fffSTakashi Iwai 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
491755196fffSTakashi Iwai 		return power_state;
4918b1b9fbd0STakashi Iwai 	if (is_active_nid_for_any(codec, nid))
491955196fffSTakashi Iwai 		return power_state;
492055196fffSTakashi Iwai 	return AC_PWRST_D3;
492155196fffSTakashi Iwai }
4922dfc6e469STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
492355196fffSTakashi Iwai 
4924ebb93c05STakashi Iwai /* mute all aamix inputs initially; parse up to the first leaves */
4925ebb93c05STakashi Iwai static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
4926ebb93c05STakashi Iwai {
4927ebb93c05STakashi Iwai 	int i, nums;
4928ebb93c05STakashi Iwai 	const hda_nid_t *conn;
4929ebb93c05STakashi Iwai 	bool has_amp;
4930ebb93c05STakashi Iwai 
4931ebb93c05STakashi Iwai 	nums = snd_hda_get_conn_list(codec, mix, &conn);
4932ebb93c05STakashi Iwai 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
4933ebb93c05STakashi Iwai 	for (i = 0; i < nums; i++) {
4934ebb93c05STakashi Iwai 		if (has_amp)
4935ef403edbSTakashi Iwai 			update_amp(codec, mix, HDA_INPUT, i,
4936ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4937ebb93c05STakashi Iwai 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
4938ef403edbSTakashi Iwai 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
4939ebb93c05STakashi Iwai 				   0xff, HDA_AMP_MUTE);
4940ebb93c05STakashi Iwai 	}
4941ebb93c05STakashi Iwai }
4942352f7f91STakashi Iwai 
4943dda42bd0STakashi Iwai /**
4944e6feb5d0STakashi Iwai  * snd_hda_gen_stream_pm - Stream power management callback
4945e6feb5d0STakashi Iwai  * @codec: the HDA codec
4946e6feb5d0STakashi Iwai  * @nid: audio widget
4947e6feb5d0STakashi Iwai  * @on: power on/off flag
4948e6feb5d0STakashi Iwai  *
4949967b1307STakashi Iwai  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
4950e6feb5d0STakashi Iwai  */
4951e6feb5d0STakashi Iwai void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
4952e6feb5d0STakashi Iwai {
4953967b1307STakashi Iwai 	if (codec->power_save_node)
4954e6feb5d0STakashi Iwai 		set_path_power(codec, nid, -1, on);
4955e6feb5d0STakashi Iwai }
4956e6feb5d0STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
4957e6feb5d0STakashi Iwai 
49586cd23b26STakashi Iwai /* forcibly mute the speaker output without caching; return true if updated */
49596cd23b26STakashi Iwai static bool force_mute_output_path(struct hda_codec *codec, hda_nid_t nid)
49606cd23b26STakashi Iwai {
49616cd23b26STakashi Iwai 	if (!nid)
49626cd23b26STakashi Iwai 		return false;
49636cd23b26STakashi Iwai 	if (!nid_has_mute(codec, nid, HDA_OUTPUT))
49646cd23b26STakashi Iwai 		return false; /* no mute, skip */
49656cd23b26STakashi Iwai 	if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
49666cd23b26STakashi Iwai 	    snd_hda_codec_amp_read(codec, nid, 1, HDA_OUTPUT, 0) &
49676cd23b26STakashi Iwai 	    HDA_AMP_MUTE)
49686cd23b26STakashi Iwai 		return false; /* both channels already muted, skip */
49696cd23b26STakashi Iwai 
49706cd23b26STakashi Iwai 	/* direct amp update without caching */
49716cd23b26STakashi Iwai 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
49726cd23b26STakashi Iwai 			    AC_AMP_SET_OUTPUT | AC_AMP_SET_LEFT |
49736cd23b26STakashi Iwai 			    AC_AMP_SET_RIGHT | HDA_AMP_MUTE);
49746cd23b26STakashi Iwai 	return true;
49756cd23b26STakashi Iwai }
49766cd23b26STakashi Iwai 
49776cd23b26STakashi Iwai /**
49786cd23b26STakashi Iwai  * snd_hda_gen_shutup_speakers - Forcibly mute the speaker outputs
49796cd23b26STakashi Iwai  * @codec: the HDA codec
49806cd23b26STakashi Iwai  *
49816cd23b26STakashi Iwai  * Forcibly mute the speaker outputs, to be called at suspend or shutdown.
49826cd23b26STakashi Iwai  *
49836cd23b26STakashi Iwai  * The mute state done by this function isn't cached, hence the original state
49846cd23b26STakashi Iwai  * will be restored at resume.
49856cd23b26STakashi Iwai  *
49866cd23b26STakashi Iwai  * Return true if the mute state has been changed.
49876cd23b26STakashi Iwai  */
49886cd23b26STakashi Iwai bool snd_hda_gen_shutup_speakers(struct hda_codec *codec)
49896cd23b26STakashi Iwai {
49906cd23b26STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
49916cd23b26STakashi Iwai 	const int *paths;
49926cd23b26STakashi Iwai 	const struct nid_path *path;
49936cd23b26STakashi Iwai 	int i, p, num_paths;
49946cd23b26STakashi Iwai 	bool updated = false;
49956cd23b26STakashi Iwai 
49966cd23b26STakashi Iwai 	/* if already powered off, do nothing */
49976cd23b26STakashi Iwai 	if (!snd_hdac_is_power_on(&codec->core))
49986cd23b26STakashi Iwai 		return false;
49996cd23b26STakashi Iwai 
50006cd23b26STakashi Iwai 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
50016cd23b26STakashi Iwai 		paths = spec->out_paths;
50026cd23b26STakashi Iwai 		num_paths = spec->autocfg.line_outs;
50036cd23b26STakashi Iwai 	} else {
50046cd23b26STakashi Iwai 		paths = spec->speaker_paths;
50056cd23b26STakashi Iwai 		num_paths = spec->autocfg.speaker_outs;
50066cd23b26STakashi Iwai 	}
50076cd23b26STakashi Iwai 
50086cd23b26STakashi Iwai 	for (i = 0; i < num_paths; i++) {
50096cd23b26STakashi Iwai 		path = snd_hda_get_path_from_idx(codec, paths[i]);
50106cd23b26STakashi Iwai 		if (!path)
50116cd23b26STakashi Iwai 			continue;
50126cd23b26STakashi Iwai 		for (p = 0; p < path->depth; p++)
50136cd23b26STakashi Iwai 			if (force_mute_output_path(codec, path->path[p]))
50146cd23b26STakashi Iwai 				updated = true;
50156cd23b26STakashi Iwai 	}
50166cd23b26STakashi Iwai 
50176cd23b26STakashi Iwai 	return updated;
50186cd23b26STakashi Iwai }
50196cd23b26STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_shutup_speakers);
50206cd23b26STakashi Iwai 
5021e6feb5d0STakashi Iwai /**
5022dda42bd0STakashi Iwai  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
5023dda42bd0STakashi Iwai  * set up the hda_gen_spec
5024dda42bd0STakashi Iwai  * @codec: the HDA codec
5025dda42bd0STakashi Iwai  * @cfg: Parsed pin configuration
50269eb413e5STakashi Iwai  *
50279eb413e5STakashi Iwai  * return 1 if successful, 0 if the proper config is not found,
5028352f7f91STakashi Iwai  * or a negative error code
5029352f7f91STakashi Iwai  */
5030352f7f91STakashi Iwai int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
50319eb413e5STakashi Iwai 				  struct auto_pin_cfg *cfg)
5032352f7f91STakashi Iwai {
5033352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5034352f7f91STakashi Iwai 	int err;
5035352f7f91STakashi Iwai 
50361c70a583STakashi Iwai 	parse_user_hints(codec);
50371c70a583STakashi Iwai 
5038e65bf997SJaroslav Kysela 	if (spec->vmaster_mute_led || spec->mic_mute_led)
5039e65bf997SJaroslav Kysela 		snd_ctl_led_request();
5040e65bf997SJaroslav Kysela 
5041e4a395e7STakashi Iwai 	if (spec->mixer_nid && !spec->mixer_merge_nid)
5042e4a395e7STakashi Iwai 		spec->mixer_merge_nid = spec->mixer_nid;
5043e4a395e7STakashi Iwai 
50449eb413e5STakashi Iwai 	if (cfg != &spec->autocfg) {
50459eb413e5STakashi Iwai 		spec->autocfg = *cfg;
50469eb413e5STakashi Iwai 		cfg = &spec->autocfg;
50479eb413e5STakashi Iwai 	}
50489eb413e5STakashi Iwai 
504998bd1115STakashi Iwai 	if (!spec->main_out_badness)
505098bd1115STakashi Iwai 		spec->main_out_badness = &hda_main_out_badness;
505198bd1115STakashi Iwai 	if (!spec->extra_out_badness)
505298bd1115STakashi Iwai 		spec->extra_out_badness = &hda_extra_out_badness;
505398bd1115STakashi Iwai 
50546fc4cb97SDavid Henningsson 	fill_all_dac_nids(codec);
50556fc4cb97SDavid Henningsson 
5056352f7f91STakashi Iwai 	if (!cfg->line_outs) {
5057352f7f91STakashi Iwai 		if (cfg->dig_outs || cfg->dig_in_pin) {
5058352f7f91STakashi Iwai 			spec->multiout.max_channels = 2;
5059352f7f91STakashi Iwai 			spec->no_analog = 1;
5060352f7f91STakashi Iwai 			goto dig_only;
5061352f7f91STakashi Iwai 		}
5062c9e4bdb7STakashi Iwai 		if (!cfg->num_inputs && !cfg->dig_in_pin)
5063352f7f91STakashi Iwai 			return 0; /* can't find valid BIOS pin config */
5064352f7f91STakashi Iwai 	}
5065352f7f91STakashi Iwai 
5066352f7f91STakashi Iwai 	if (!spec->no_primary_hp &&
5067352f7f91STakashi Iwai 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
5068352f7f91STakashi Iwai 	    cfg->line_outs <= cfg->hp_outs) {
5069352f7f91STakashi Iwai 		/* use HP as primary out */
5070352f7f91STakashi Iwai 		cfg->speaker_outs = cfg->line_outs;
5071352f7f91STakashi Iwai 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
5072352f7f91STakashi Iwai 		       sizeof(cfg->speaker_pins));
5073352f7f91STakashi Iwai 		cfg->line_outs = cfg->hp_outs;
5074352f7f91STakashi Iwai 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
5075352f7f91STakashi Iwai 		cfg->hp_outs = 0;
5076352f7f91STakashi Iwai 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
5077352f7f91STakashi Iwai 		cfg->line_out_type = AUTO_PIN_HP_OUT;
5078352f7f91STakashi Iwai 	}
5079352f7f91STakashi Iwai 
5080352f7f91STakashi Iwai 	err = parse_output_paths(codec);
5081352f7f91STakashi Iwai 	if (err < 0)
5082352f7f91STakashi Iwai 		return err;
5083352f7f91STakashi Iwai 	err = create_multi_channel_mode(codec);
5084352f7f91STakashi Iwai 	if (err < 0)
5085352f7f91STakashi Iwai 		return err;
5086352f7f91STakashi Iwai 	err = create_multi_out_ctls(codec, cfg);
5087352f7f91STakashi Iwai 	if (err < 0)
5088352f7f91STakashi Iwai 		return err;
5089352f7f91STakashi Iwai 	err = create_hp_out_ctls(codec);
5090352f7f91STakashi Iwai 	if (err < 0)
5091352f7f91STakashi Iwai 		return err;
5092352f7f91STakashi Iwai 	err = create_speaker_out_ctls(codec);
5093352f7f91STakashi Iwai 	if (err < 0)
5094352f7f91STakashi Iwai 		return err;
509538cf6f1aSTakashi Iwai 	err = create_indep_hp_ctls(codec);
509638cf6f1aSTakashi Iwai 	if (err < 0)
509738cf6f1aSTakashi Iwai 		return err;
5098c30aa7b2STakashi Iwai 	err = create_loopback_mixing_ctl(codec);
5099c30aa7b2STakashi Iwai 	if (err < 0)
5100c30aa7b2STakashi Iwai 		return err;
5101967303daSTakashi Iwai 	err = create_hp_mic(codec);
5102352f7f91STakashi Iwai 	if (err < 0)
5103352f7f91STakashi Iwai 		return err;
5104352f7f91STakashi Iwai 	err = create_input_ctls(codec);
5105352f7f91STakashi Iwai 	if (err < 0)
5106352f7f91STakashi Iwai 		return err;
5107352f7f91STakashi Iwai 
5108e6feb5d0STakashi Iwai 	/* add power-down pin callbacks at first */
5109e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, false);
5110e6feb5d0STakashi Iwai 
5111a07a949bSTakashi Iwai 	spec->const_channel_count = spec->ext_channel_count;
5112a07a949bSTakashi Iwai 	/* check the multiple speaker and headphone pins */
5113a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
5114a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5115a07a949bSTakashi Iwai 						cfg->speaker_outs * 2);
5116a07a949bSTakashi Iwai 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
5117a07a949bSTakashi Iwai 		spec->const_channel_count = max(spec->const_channel_count,
5118a07a949bSTakashi Iwai 						cfg->hp_outs * 2);
5119352f7f91STakashi Iwai 	spec->multiout.max_channels = max(spec->ext_channel_count,
5120352f7f91STakashi Iwai 					  spec->const_channel_count);
5121352f7f91STakashi Iwai 
5122352f7f91STakashi Iwai 	err = check_auto_mute_availability(codec);
5123352f7f91STakashi Iwai 	if (err < 0)
5124352f7f91STakashi Iwai 		return err;
5125352f7f91STakashi Iwai 
5126352f7f91STakashi Iwai 	err = check_dyn_adc_switch(codec);
5127352f7f91STakashi Iwai 	if (err < 0)
5128352f7f91STakashi Iwai 		return err;
5129352f7f91STakashi Iwai 
5130352f7f91STakashi Iwai 	err = check_auto_mic_availability(codec);
5131352f7f91STakashi Iwai 	if (err < 0)
5132352f7f91STakashi Iwai 		return err;
5133352f7f91STakashi Iwai 
5134f1e762ddSTakashi Iwai 	/* add stereo mix if available and not enabled yet */
5135f1e762ddSTakashi Iwai 	if (!spec->auto_mic && spec->mixer_nid &&
513674f14b36STakashi Iwai 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
513774f14b36STakashi Iwai 	    spec->input_mux.num_items > 1) {
5138f1e762ddSTakashi Iwai 		err = parse_capture_source(codec, spec->mixer_nid,
5139f1e762ddSTakashi Iwai 					   CFG_IDX_MIX, spec->num_all_adcs,
5140f1e762ddSTakashi Iwai 					   "Stereo Mix", 0);
5141f1e762ddSTakashi Iwai 		if (err < 0)
5142f1e762ddSTakashi Iwai 			return err;
5143f1e762ddSTakashi Iwai 	}
5144f1e762ddSTakashi Iwai 
5145f1e762ddSTakashi Iwai 
5146352f7f91STakashi Iwai 	err = create_capture_mixers(codec);
5147352f7f91STakashi Iwai 	if (err < 0)
5148352f7f91STakashi Iwai 		return err;
5149352f7f91STakashi Iwai 
5150352f7f91STakashi Iwai 	err = parse_mic_boost(codec);
5151352f7f91STakashi Iwai 	if (err < 0)
5152352f7f91STakashi Iwai 		return err;
5153352f7f91STakashi Iwai 
5154ced4cefcSTakashi Iwai 	/* create "Headphone Mic Jack Mode" if no input selection is
5155ced4cefcSTakashi Iwai 	 * available (or user specifies add_jack_modes hint)
5156ced4cefcSTakashi Iwai 	 */
5157ced4cefcSTakashi Iwai 	if (spec->hp_mic_pin &&
5158ced4cefcSTakashi Iwai 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
5159ced4cefcSTakashi Iwai 	     spec->add_jack_modes)) {
5160ced4cefcSTakashi Iwai 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
5161ced4cefcSTakashi Iwai 		if (err < 0)
5162ced4cefcSTakashi Iwai 			return err;
5163ced4cefcSTakashi Iwai 	}
5164ced4cefcSTakashi Iwai 
5165f811c3cfSTakashi Iwai 	if (spec->add_jack_modes) {
5166978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
5167978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->line_outs,
5168978e77e7STakashi Iwai 						    cfg->line_out_pins);
5169978e77e7STakashi Iwai 			if (err < 0)
5170978e77e7STakashi Iwai 				return err;
5171978e77e7STakashi Iwai 		}
5172978e77e7STakashi Iwai 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
5173978e77e7STakashi Iwai 			err = create_out_jack_modes(codec, cfg->hp_outs,
5174978e77e7STakashi Iwai 						    cfg->hp_pins);
5175978e77e7STakashi Iwai 			if (err < 0)
5176978e77e7STakashi Iwai 				return err;
5177978e77e7STakashi Iwai 		}
5178978e77e7STakashi Iwai 	}
5179978e77e7STakashi Iwai 
5180e6feb5d0STakashi Iwai 	/* add power-up pin callbacks at last */
5181e6feb5d0STakashi Iwai 	add_all_pin_power_ctls(codec, true);
5182e6feb5d0STakashi Iwai 
5183ebb93c05STakashi Iwai 	/* mute all aamix input initially */
5184ebb93c05STakashi Iwai 	if (spec->mixer_nid)
5185ebb93c05STakashi Iwai 		mute_all_mixer_nid(codec, spec->mixer_nid);
5186ebb93c05STakashi Iwai 
5187352f7f91STakashi Iwai  dig_only:
5188352f7f91STakashi Iwai 	parse_digital(codec);
5189352f7f91STakashi Iwai 
519049fb1897STakashi Iwai 	if (spec->power_down_unused || codec->power_save_node) {
519124fef902STakashi Iwai 		if (!codec->power_filter)
519255196fffSTakashi Iwai 			codec->power_filter = snd_hda_gen_path_power_filter;
519349fb1897STakashi Iwai 		if (!codec->patch_ops.stream_pm)
519449fb1897STakashi Iwai 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
519549fb1897STakashi Iwai 	}
519655196fffSTakashi Iwai 
51977504b6cdSTakashi Iwai 	if (!spec->no_analog && spec->beep_nid) {
51987504b6cdSTakashi Iwai 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
51997504b6cdSTakashi Iwai 		if (err < 0)
52007504b6cdSTakashi Iwai 			return err;
5201967b1307STakashi Iwai 		if (codec->beep && codec->power_save_node) {
52025ccf835cSTakashi Iwai 			err = add_fake_beep_paths(codec);
52035ccf835cSTakashi Iwai 			if (err < 0)
52045ccf835cSTakashi Iwai 				return err;
52055ccf835cSTakashi Iwai 			codec->beep->power_hook = beep_power_hook;
52065ccf835cSTakashi Iwai 		}
52077504b6cdSTakashi Iwai 	}
52087504b6cdSTakashi Iwai 
5209352f7f91STakashi Iwai 	return 1;
5210352f7f91STakashi Iwai }
52112698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
5212352f7f91STakashi Iwai 
5213352f7f91STakashi Iwai 
5214352f7f91STakashi Iwai /*
5215352f7f91STakashi Iwai  * Build control elements
5216352f7f91STakashi Iwai  */
5217352f7f91STakashi Iwai 
52189ab0cb30STakashi Iwai /* follower controls for virtual master */
52199ab0cb30STakashi Iwai static const char * const follower_pfxs[] = {
5220352f7f91STakashi Iwai 	"Front", "Surround", "Center", "LFE", "Side",
5221352f7f91STakashi Iwai 	"Headphone", "Speaker", "Mono", "Line Out",
5222352f7f91STakashi Iwai 	"CLFE", "Bass Speaker", "PCM",
5223ee79c69aSTakashi Iwai 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
5224ee79c69aSTakashi Iwai 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
522503ad6a8cSDavid Henningsson 	"Headphone Side", "Headphone+LO", "Speaker+LO",
5226352f7f91STakashi Iwai 	NULL,
5227352f7f91STakashi Iwai };
5228352f7f91STakashi Iwai 
5229dda42bd0STakashi Iwai /**
5230dda42bd0STakashi Iwai  * snd_hda_gen_build_controls - Build controls from the parsed results
5231dda42bd0STakashi Iwai  * @codec: the HDA codec
5232dda42bd0STakashi Iwai  *
5233dda42bd0STakashi Iwai  * Pass this to build_controls patch_ops.
5234dda42bd0STakashi Iwai  */
5235352f7f91STakashi Iwai int snd_hda_gen_build_controls(struct hda_codec *codec)
5236352f7f91STakashi Iwai {
5237352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5238352f7f91STakashi Iwai 	int err;
5239352f7f91STakashi Iwai 
524036502d02STakashi Iwai 	if (spec->kctls.used) {
5241352f7f91STakashi Iwai 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5242352f7f91STakashi Iwai 		if (err < 0)
5243352f7f91STakashi Iwai 			return err;
524436502d02STakashi Iwai 	}
5245352f7f91STakashi Iwai 
5246352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid) {
5247352f7f91STakashi Iwai 		err = snd_hda_create_dig_out_ctls(codec,
5248352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5249352f7f91STakashi Iwai 						  spec->multiout.dig_out_nid,
5250bbbc7e85STakashi Iwai 						  spec->pcm_rec[1]->pcm_type);
5251352f7f91STakashi Iwai 		if (err < 0)
5252352f7f91STakashi Iwai 			return err;
5253352f7f91STakashi Iwai 		if (!spec->no_analog) {
5254352f7f91STakashi Iwai 			err = snd_hda_create_spdif_share_sw(codec,
5255352f7f91STakashi Iwai 							    &spec->multiout);
5256352f7f91STakashi Iwai 			if (err < 0)
5257352f7f91STakashi Iwai 				return err;
5258352f7f91STakashi Iwai 			spec->multiout.share_spdif = 1;
5259352f7f91STakashi Iwai 		}
5260352f7f91STakashi Iwai 	}
5261352f7f91STakashi Iwai 	if (spec->dig_in_nid) {
5262352f7f91STakashi Iwai 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5263352f7f91STakashi Iwai 		if (err < 0)
5264352f7f91STakashi Iwai 			return err;
5265352f7f91STakashi Iwai 	}
5266352f7f91STakashi Iwai 
5267352f7f91STakashi Iwai 	/* if we have no master control, let's create it */
52687480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5269352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5270352f7f91STakashi Iwai 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
52719ab0cb30STakashi Iwai 					  spec->vmaster_tlv, follower_pfxs,
5272e65bf997SJaroslav Kysela 					  "Playback Volume", 0);
5273352f7f91STakashi Iwai 		if (err < 0)
5274352f7f91STakashi Iwai 			return err;
5275352f7f91STakashi Iwai 	}
52767480316cSTakashi Iwai 	if (!spec->no_analog && !spec->suppress_vmaster &&
5277352f7f91STakashi Iwai 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5278352f7f91STakashi Iwai 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
52799ab0cb30STakashi Iwai 					    NULL, follower_pfxs,
5280e65bf997SJaroslav Kysela 					    "Playback Switch", true,
5281e65bf997SJaroslav Kysela 					    spec->vmaster_mute_led ?
5282e65bf997SJaroslav Kysela 						SNDRV_CTL_ELEM_ACCESS_SPK_LED : 0,
5283e65bf997SJaroslav Kysela 					    &spec->vmaster_mute.sw_kctl);
5284352f7f91STakashi Iwai 		if (err < 0)
5285352f7f91STakashi Iwai 			return err;
5286b63eae0aSTakashi Iwai 		if (spec->vmaster_mute.hook) {
5287e65bf997SJaroslav Kysela 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute);
5288b63eae0aSTakashi Iwai 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5289b63eae0aSTakashi Iwai 		}
5290352f7f91STakashi Iwai 	}
5291352f7f91STakashi Iwai 
5292352f7f91STakashi Iwai 	free_kctls(spec); /* no longer needed */
5293352f7f91STakashi Iwai 
5294352f7f91STakashi Iwai 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5295352f7f91STakashi Iwai 	if (err < 0)
5296352f7f91STakashi Iwai 		return err;
5297352f7f91STakashi Iwai 
5298352f7f91STakashi Iwai 	return 0;
5299352f7f91STakashi Iwai }
53002698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5301352f7f91STakashi Iwai 
5302352f7f91STakashi Iwai 
5303352f7f91STakashi Iwai /*
5304352f7f91STakashi Iwai  * PCM definitions
5305352f7f91STakashi Iwai  */
5306352f7f91STakashi Iwai 
5307e6b85f3cSTakashi Iwai static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5308e6b85f3cSTakashi Iwai 				   struct hda_codec *codec,
5309e6b85f3cSTakashi Iwai 				   struct snd_pcm_substream *substream,
5310e6b85f3cSTakashi Iwai 				   int action)
5311e6b85f3cSTakashi Iwai {
5312e6b85f3cSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5313e6b85f3cSTakashi Iwai 	if (spec->pcm_playback_hook)
5314e6b85f3cSTakashi Iwai 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5315e6b85f3cSTakashi Iwai }
5316e6b85f3cSTakashi Iwai 
5317ac2e8736STakashi Iwai static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5318ac2e8736STakashi Iwai 				  struct hda_codec *codec,
5319ac2e8736STakashi Iwai 				  struct snd_pcm_substream *substream,
5320ac2e8736STakashi Iwai 				  int action)
5321ac2e8736STakashi Iwai {
5322ac2e8736STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5323ac2e8736STakashi Iwai 	if (spec->pcm_capture_hook)
5324ac2e8736STakashi Iwai 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5325ac2e8736STakashi Iwai }
5326ac2e8736STakashi Iwai 
5327352f7f91STakashi Iwai /*
5328352f7f91STakashi Iwai  * Analog playback callbacks
5329352f7f91STakashi Iwai  */
5330352f7f91STakashi Iwai static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5331352f7f91STakashi Iwai 			     struct hda_codec *codec,
5332352f7f91STakashi Iwai 			     struct snd_pcm_substream *substream)
5333352f7f91STakashi Iwai {
5334352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
533538cf6f1aSTakashi Iwai 	int err;
533638cf6f1aSTakashi Iwai 
533738cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
533838cf6f1aSTakashi Iwai 	err = snd_hda_multi_out_analog_open(codec,
533938cf6f1aSTakashi Iwai 					    &spec->multiout, substream,
5340352f7f91STakashi Iwai 					     hinfo);
5341e6b85f3cSTakashi Iwai 	if (!err) {
534238cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5343e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5344e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_OPEN);
5345e6b85f3cSTakashi Iwai 	}
534638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
534738cf6f1aSTakashi Iwai 	return err;
5348352f7f91STakashi Iwai }
5349352f7f91STakashi Iwai 
5350352f7f91STakashi Iwai static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
535197ec558aSTakashi Iwai 				struct hda_codec *codec,
535297ec558aSTakashi Iwai 				unsigned int stream_tag,
535397ec558aSTakashi Iwai 				unsigned int format,
535497ec558aSTakashi Iwai 				struct snd_pcm_substream *substream)
535597ec558aSTakashi Iwai {
5356352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5357e6b85f3cSTakashi Iwai 	int err;
5358e6b85f3cSTakashi Iwai 
5359e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5360352f7f91STakashi Iwai 					       stream_tag, format, substream);
5361e6b85f3cSTakashi Iwai 	if (!err)
5362e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5363e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_PREPARE);
5364e6b85f3cSTakashi Iwai 	return err;
5365352f7f91STakashi Iwai }
536697ec558aSTakashi Iwai 
5367352f7f91STakashi Iwai static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5368352f7f91STakashi Iwai 				struct hda_codec *codec,
5369352f7f91STakashi Iwai 				struct snd_pcm_substream *substream)
5370352f7f91STakashi Iwai {
5371352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5372e6b85f3cSTakashi Iwai 	int err;
5373e6b85f3cSTakashi Iwai 
5374e6b85f3cSTakashi Iwai 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5375e6b85f3cSTakashi Iwai 	if (!err)
5376e6b85f3cSTakashi Iwai 		call_pcm_playback_hook(hinfo, codec, substream,
5377e6b85f3cSTakashi Iwai 				       HDA_GEN_PCM_ACT_CLEANUP);
5378e6b85f3cSTakashi Iwai 	return err;
5379352f7f91STakashi Iwai }
5380352f7f91STakashi Iwai 
538138cf6f1aSTakashi Iwai static int playback_pcm_close(struct hda_pcm_stream *hinfo,
538238cf6f1aSTakashi Iwai 			      struct hda_codec *codec,
538338cf6f1aSTakashi Iwai 			      struct snd_pcm_substream *substream)
538438cf6f1aSTakashi Iwai {
538538cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
538638cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
538738cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5388e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5389e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
539038cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
539138cf6f1aSTakashi Iwai 	return 0;
539238cf6f1aSTakashi Iwai }
539338cf6f1aSTakashi Iwai 
5394ac2e8736STakashi Iwai static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5395ac2e8736STakashi Iwai 			    struct hda_codec *codec,
5396ac2e8736STakashi Iwai 			    struct snd_pcm_substream *substream)
5397ac2e8736STakashi Iwai {
5398ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5399ac2e8736STakashi Iwai 	return 0;
5400ac2e8736STakashi Iwai }
5401ac2e8736STakashi Iwai 
5402ac2e8736STakashi Iwai static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5403ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5404ac2e8736STakashi Iwai 			       unsigned int stream_tag,
5405ac2e8736STakashi Iwai 			       unsigned int format,
5406ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5407ac2e8736STakashi Iwai {
5408ac2e8736STakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5409ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5410ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
5411ac2e8736STakashi Iwai 	return 0;
5412ac2e8736STakashi Iwai }
5413ac2e8736STakashi Iwai 
5414ac2e8736STakashi Iwai static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5415ac2e8736STakashi Iwai 			       struct hda_codec *codec,
5416ac2e8736STakashi Iwai 			       struct snd_pcm_substream *substream)
5417ac2e8736STakashi Iwai {
5418ac2e8736STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5419ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5420ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
5421ac2e8736STakashi Iwai 	return 0;
5422ac2e8736STakashi Iwai }
5423ac2e8736STakashi Iwai 
5424ac2e8736STakashi Iwai static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5425ac2e8736STakashi Iwai 			     struct hda_codec *codec,
5426ac2e8736STakashi Iwai 			     struct snd_pcm_substream *substream)
5427ac2e8736STakashi Iwai {
5428ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5429ac2e8736STakashi Iwai 	return 0;
5430ac2e8736STakashi Iwai }
5431ac2e8736STakashi Iwai 
543238cf6f1aSTakashi Iwai static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
543338cf6f1aSTakashi Iwai 				 struct hda_codec *codec,
543438cf6f1aSTakashi Iwai 				 struct snd_pcm_substream *substream)
543538cf6f1aSTakashi Iwai {
543638cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
543738cf6f1aSTakashi Iwai 	int err = 0;
543838cf6f1aSTakashi Iwai 
543938cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
5440d1f15e06STakashi Iwai 	if (spec->indep_hp && !spec->indep_hp_enabled)
544138cf6f1aSTakashi Iwai 		err = -EBUSY;
544238cf6f1aSTakashi Iwai 	else
544338cf6f1aSTakashi Iwai 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5444e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5445e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_OPEN);
544638cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
544738cf6f1aSTakashi Iwai 	return err;
544838cf6f1aSTakashi Iwai }
544938cf6f1aSTakashi Iwai 
545038cf6f1aSTakashi Iwai static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
545138cf6f1aSTakashi Iwai 				  struct hda_codec *codec,
545238cf6f1aSTakashi Iwai 				  struct snd_pcm_substream *substream)
545338cf6f1aSTakashi Iwai {
545438cf6f1aSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
545538cf6f1aSTakashi Iwai 	mutex_lock(&spec->pcm_mutex);
545638cf6f1aSTakashi Iwai 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5457e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5458e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLOSE);
545938cf6f1aSTakashi Iwai 	mutex_unlock(&spec->pcm_mutex);
546038cf6f1aSTakashi Iwai 	return 0;
546138cf6f1aSTakashi Iwai }
546238cf6f1aSTakashi Iwai 
5463e6b85f3cSTakashi Iwai static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5464e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5465e6b85f3cSTakashi Iwai 				    unsigned int stream_tag,
5466e6b85f3cSTakashi Iwai 				    unsigned int format,
5467e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5468e6b85f3cSTakashi Iwai {
5469e6b85f3cSTakashi Iwai 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5470e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5471e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_PREPARE);
5472e6b85f3cSTakashi Iwai 	return 0;
5473e6b85f3cSTakashi Iwai }
5474e6b85f3cSTakashi Iwai 
5475e6b85f3cSTakashi Iwai static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5476e6b85f3cSTakashi Iwai 				    struct hda_codec *codec,
5477e6b85f3cSTakashi Iwai 				    struct snd_pcm_substream *substream)
5478e6b85f3cSTakashi Iwai {
5479e6b85f3cSTakashi Iwai 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5480e6b85f3cSTakashi Iwai 	call_pcm_playback_hook(hinfo, codec, substream,
5481e6b85f3cSTakashi Iwai 			       HDA_GEN_PCM_ACT_CLEANUP);
5482e6b85f3cSTakashi Iwai 	return 0;
5483e6b85f3cSTakashi Iwai }
5484e6b85f3cSTakashi Iwai 
5485352f7f91STakashi Iwai /*
5486352f7f91STakashi Iwai  * Digital out
5487352f7f91STakashi Iwai  */
5488352f7f91STakashi Iwai static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5489352f7f91STakashi Iwai 				 struct hda_codec *codec,
5490352f7f91STakashi Iwai 				 struct snd_pcm_substream *substream)
5491352f7f91STakashi Iwai {
5492352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5493352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5494352f7f91STakashi Iwai }
5495352f7f91STakashi Iwai 
5496352f7f91STakashi Iwai static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5497352f7f91STakashi Iwai 				    struct hda_codec *codec,
5498352f7f91STakashi Iwai 				    unsigned int stream_tag,
5499352f7f91STakashi Iwai 				    unsigned int format,
5500352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5501352f7f91STakashi Iwai {
5502352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5503352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5504352f7f91STakashi Iwai 					     stream_tag, format, substream);
5505352f7f91STakashi Iwai }
5506352f7f91STakashi Iwai 
5507352f7f91STakashi Iwai static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5508352f7f91STakashi Iwai 				    struct hda_codec *codec,
5509352f7f91STakashi Iwai 				    struct snd_pcm_substream *substream)
5510352f7f91STakashi Iwai {
5511352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5512352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5513352f7f91STakashi Iwai }
5514352f7f91STakashi Iwai 
5515352f7f91STakashi Iwai static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5516352f7f91STakashi Iwai 				  struct hda_codec *codec,
5517352f7f91STakashi Iwai 				  struct snd_pcm_substream *substream)
5518352f7f91STakashi Iwai {
5519352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5520352f7f91STakashi Iwai 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5521352f7f91STakashi Iwai }
5522352f7f91STakashi Iwai 
5523352f7f91STakashi Iwai /*
5524352f7f91STakashi Iwai  * Analog capture
5525352f7f91STakashi Iwai  */
5526ac2e8736STakashi Iwai #define alt_capture_pcm_open	capture_pcm_open
5527ac2e8736STakashi Iwai #define alt_capture_pcm_close	capture_pcm_close
5528ac2e8736STakashi Iwai 
5529352f7f91STakashi Iwai static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5530352f7f91STakashi Iwai 				   struct hda_codec *codec,
5531352f7f91STakashi Iwai 				   unsigned int stream_tag,
5532352f7f91STakashi Iwai 				   unsigned int format,
5533352f7f91STakashi Iwai 				   struct snd_pcm_substream *substream)
5534352f7f91STakashi Iwai {
5535352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5536352f7f91STakashi Iwai 
5537352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
553897ec558aSTakashi Iwai 				   stream_tag, 0, format);
5539ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5540ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_PREPARE);
554197ec558aSTakashi Iwai 	return 0;
554297ec558aSTakashi Iwai }
554397ec558aSTakashi Iwai 
5544352f7f91STakashi Iwai static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
554597ec558aSTakashi Iwai 				   struct hda_codec *codec,
554697ec558aSTakashi Iwai 				   struct snd_pcm_substream *substream)
554797ec558aSTakashi Iwai {
5548352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
554997ec558aSTakashi Iwai 
5550352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec,
5551352f7f91STakashi Iwai 				     spec->adc_nids[substream->number + 1]);
5552ac2e8736STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream,
5553ac2e8736STakashi Iwai 			      HDA_GEN_PCM_ACT_CLEANUP);
555497ec558aSTakashi Iwai 	return 0;
555597ec558aSTakashi Iwai }
555697ec558aSTakashi Iwai 
5557352f7f91STakashi Iwai /*
5558352f7f91STakashi Iwai  */
5559352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_playback = {
5560352f7f91STakashi Iwai 	.substreams = 1,
5561352f7f91STakashi Iwai 	.channels_min = 2,
5562352f7f91STakashi Iwai 	.channels_max = 8,
5563352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5564352f7f91STakashi Iwai 	.ops = {
5565352f7f91STakashi Iwai 		.open = playback_pcm_open,
556638cf6f1aSTakashi Iwai 		.close = playback_pcm_close,
5567352f7f91STakashi Iwai 		.prepare = playback_pcm_prepare,
5568352f7f91STakashi Iwai 		.cleanup = playback_pcm_cleanup
5569352f7f91STakashi Iwai 	},
5570352f7f91STakashi Iwai };
5571352f7f91STakashi Iwai 
5572352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_capture = {
5573352f7f91STakashi Iwai 	.substreams = 1,
5574352f7f91STakashi Iwai 	.channels_min = 2,
5575352f7f91STakashi Iwai 	.channels_max = 2,
5576352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5577ac2e8736STakashi Iwai 	.ops = {
5578ac2e8736STakashi Iwai 		.open = capture_pcm_open,
5579ac2e8736STakashi Iwai 		.close = capture_pcm_close,
5580ac2e8736STakashi Iwai 		.prepare = capture_pcm_prepare,
5581ac2e8736STakashi Iwai 		.cleanup = capture_pcm_cleanup
5582ac2e8736STakashi Iwai 	},
5583352f7f91STakashi Iwai };
5584352f7f91STakashi Iwai 
5585352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_playback = {
5586352f7f91STakashi Iwai 	.substreams = 1,
5587352f7f91STakashi Iwai 	.channels_min = 2,
5588352f7f91STakashi Iwai 	.channels_max = 2,
5589352f7f91STakashi Iwai 	/* NID is set in build_pcms */
559038cf6f1aSTakashi Iwai 	.ops = {
559138cf6f1aSTakashi Iwai 		.open = alt_playback_pcm_open,
5592e6b85f3cSTakashi Iwai 		.close = alt_playback_pcm_close,
5593e6b85f3cSTakashi Iwai 		.prepare = alt_playback_pcm_prepare,
5594e6b85f3cSTakashi Iwai 		.cleanup = alt_playback_pcm_cleanup
559538cf6f1aSTakashi Iwai 	},
5596352f7f91STakashi Iwai };
5597352f7f91STakashi Iwai 
5598352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_analog_alt_capture = {
5599352f7f91STakashi Iwai 	.substreams = 2, /* can be overridden */
5600352f7f91STakashi Iwai 	.channels_min = 2,
5601352f7f91STakashi Iwai 	.channels_max = 2,
5602352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5603352f7f91STakashi Iwai 	.ops = {
5604ac2e8736STakashi Iwai 		.open = alt_capture_pcm_open,
5605ac2e8736STakashi Iwai 		.close = alt_capture_pcm_close,
5606352f7f91STakashi Iwai 		.prepare = alt_capture_pcm_prepare,
5607352f7f91STakashi Iwai 		.cleanup = alt_capture_pcm_cleanup
5608352f7f91STakashi Iwai 	},
5609352f7f91STakashi Iwai };
5610352f7f91STakashi Iwai 
5611352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_playback = {
5612352f7f91STakashi Iwai 	.substreams = 1,
5613352f7f91STakashi Iwai 	.channels_min = 2,
5614352f7f91STakashi Iwai 	.channels_max = 2,
5615352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5616352f7f91STakashi Iwai 	.ops = {
5617352f7f91STakashi Iwai 		.open = dig_playback_pcm_open,
5618352f7f91STakashi Iwai 		.close = dig_playback_pcm_close,
5619352f7f91STakashi Iwai 		.prepare = dig_playback_pcm_prepare,
5620352f7f91STakashi Iwai 		.cleanup = dig_playback_pcm_cleanup
5621352f7f91STakashi Iwai 	},
5622352f7f91STakashi Iwai };
5623352f7f91STakashi Iwai 
5624352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_digital_capture = {
5625352f7f91STakashi Iwai 	.substreams = 1,
5626352f7f91STakashi Iwai 	.channels_min = 2,
5627352f7f91STakashi Iwai 	.channels_max = 2,
5628352f7f91STakashi Iwai 	/* NID is set in build_pcms */
5629352f7f91STakashi Iwai };
5630352f7f91STakashi Iwai 
5631352f7f91STakashi Iwai /* Used by build_pcms to flag that a PCM has no playback stream */
5632352f7f91STakashi Iwai static const struct hda_pcm_stream pcm_null_stream = {
5633352f7f91STakashi Iwai 	.substreams = 0,
5634352f7f91STakashi Iwai 	.channels_min = 0,
5635352f7f91STakashi Iwai 	.channels_max = 0,
5636352f7f91STakashi Iwai };
5637352f7f91STakashi Iwai 
5638352f7f91STakashi Iwai /*
5639352f7f91STakashi Iwai  * dynamic changing ADC PCM streams
5640352f7f91STakashi Iwai  */
5641352f7f91STakashi Iwai static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
56421da177e4SLinus Torvalds {
5643352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5644352f7f91STakashi Iwai 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
56451da177e4SLinus Torvalds 
5646352f7f91STakashi Iwai 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5647352f7f91STakashi Iwai 		/* stream is running, let's swap the current ADC */
5648352f7f91STakashi Iwai 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5649352f7f91STakashi Iwai 		spec->cur_adc = new_adc;
5650352f7f91STakashi Iwai 		snd_hda_codec_setup_stream(codec, new_adc,
5651352f7f91STakashi Iwai 					   spec->cur_adc_stream_tag, 0,
5652352f7f91STakashi Iwai 					   spec->cur_adc_format);
5653352f7f91STakashi Iwai 		return true;
5654352f7f91STakashi Iwai 	}
5655352f7f91STakashi Iwai 	return false;
5656352f7f91STakashi Iwai }
5657352f7f91STakashi Iwai 
5658352f7f91STakashi Iwai /* analog capture with dynamic dual-adc changes */
5659352f7f91STakashi Iwai static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5660352f7f91STakashi Iwai 				       struct hda_codec *codec,
5661352f7f91STakashi Iwai 				       unsigned int stream_tag,
5662352f7f91STakashi Iwai 				       unsigned int format,
5663352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5664352f7f91STakashi Iwai {
5665352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5666352f7f91STakashi Iwai 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5667352f7f91STakashi Iwai 	spec->cur_adc_stream_tag = stream_tag;
5668352f7f91STakashi Iwai 	spec->cur_adc_format = format;
5669352f7f91STakashi Iwai 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
56704f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
56711da177e4SLinus Torvalds 	return 0;
56721da177e4SLinus Torvalds }
56731da177e4SLinus Torvalds 
5674352f7f91STakashi Iwai static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5675352f7f91STakashi Iwai 				       struct hda_codec *codec,
5676352f7f91STakashi Iwai 				       struct snd_pcm_substream *substream)
5677352f7f91STakashi Iwai {
5678352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5679352f7f91STakashi Iwai 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5680352f7f91STakashi Iwai 	spec->cur_adc = 0;
56814f29efc0STakashi Iwai 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
5682352f7f91STakashi Iwai 	return 0;
5683352f7f91STakashi Iwai }
5684352f7f91STakashi Iwai 
5685352f7f91STakashi Iwai static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5686352f7f91STakashi Iwai 	.substreams = 1,
5687352f7f91STakashi Iwai 	.channels_min = 2,
5688352f7f91STakashi Iwai 	.channels_max = 2,
5689352f7f91STakashi Iwai 	.nid = 0, /* fill later */
5690352f7f91STakashi Iwai 	.ops = {
5691352f7f91STakashi Iwai 		.prepare = dyn_adc_capture_pcm_prepare,
5692352f7f91STakashi Iwai 		.cleanup = dyn_adc_capture_pcm_cleanup
5693352f7f91STakashi Iwai 	},
5694352f7f91STakashi Iwai };
5695352f7f91STakashi Iwai 
5696f873e536STakashi Iwai static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5697f873e536STakashi Iwai 				 const char *chip_name)
5698f873e536STakashi Iwai {
5699f873e536STakashi Iwai 	char *p;
5700f873e536STakashi Iwai 
5701f873e536STakashi Iwai 	if (*str)
5702f873e536STakashi Iwai 		return;
570375b1a8f9SJoe Perches 	strscpy(str, chip_name, len);
5704f873e536STakashi Iwai 
5705f873e536STakashi Iwai 	/* drop non-alnum chars after a space */
5706f873e536STakashi Iwai 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5707f873e536STakashi Iwai 		if (!isalnum(p[1])) {
5708f873e536STakashi Iwai 			*p = 0;
5709f873e536STakashi Iwai 			break;
5710f873e536STakashi Iwai 		}
5711f873e536STakashi Iwai 	}
5712f873e536STakashi Iwai 	strlcat(str, sfx, len);
5713f873e536STakashi Iwai }
5714f873e536STakashi Iwai 
5715fb83b635STakashi Iwai /* copy PCM stream info from @default_str, and override non-NULL entries
5716fb83b635STakashi Iwai  * from @spec_str and @nid
5717fb83b635STakashi Iwai  */
5718fb83b635STakashi Iwai static void setup_pcm_stream(struct hda_pcm_stream *str,
5719fb83b635STakashi Iwai 			     const struct hda_pcm_stream *default_str,
5720fb83b635STakashi Iwai 			     const struct hda_pcm_stream *spec_str,
5721fb83b635STakashi Iwai 			     hda_nid_t nid)
5722fb83b635STakashi Iwai {
5723fb83b635STakashi Iwai 	*str = *default_str;
5724fb83b635STakashi Iwai 	if (nid)
5725fb83b635STakashi Iwai 		str->nid = nid;
5726fb83b635STakashi Iwai 	if (spec_str) {
5727fb83b635STakashi Iwai 		if (spec_str->substreams)
5728fb83b635STakashi Iwai 			str->substreams = spec_str->substreams;
5729fb83b635STakashi Iwai 		if (spec_str->channels_min)
5730fb83b635STakashi Iwai 			str->channels_min = spec_str->channels_min;
5731fb83b635STakashi Iwai 		if (spec_str->channels_max)
5732fb83b635STakashi Iwai 			str->channels_max = spec_str->channels_max;
5733fb83b635STakashi Iwai 		if (spec_str->rates)
5734fb83b635STakashi Iwai 			str->rates = spec_str->rates;
5735fb83b635STakashi Iwai 		if (spec_str->formats)
5736fb83b635STakashi Iwai 			str->formats = spec_str->formats;
5737fb83b635STakashi Iwai 		if (spec_str->maxbps)
5738fb83b635STakashi Iwai 			str->maxbps = spec_str->maxbps;
5739fb83b635STakashi Iwai 	}
5740fb83b635STakashi Iwai }
5741fb83b635STakashi Iwai 
5742dda42bd0STakashi Iwai /**
5743dda42bd0STakashi Iwai  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5744dda42bd0STakashi Iwai  * @codec: the HDA codec
5745dda42bd0STakashi Iwai  *
5746dda42bd0STakashi Iwai  * Pass this to build_pcms patch_ops.
5747dda42bd0STakashi Iwai  */
5748352f7f91STakashi Iwai int snd_hda_gen_build_pcms(struct hda_codec *codec)
5749352f7f91STakashi Iwai {
5750352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5751bbbc7e85STakashi Iwai 	struct hda_pcm *info;
5752352f7f91STakashi Iwai 	bool have_multi_adcs;
5753352f7f91STakashi Iwai 
5754352f7f91STakashi Iwai 	if (spec->no_analog)
5755352f7f91STakashi Iwai 		goto skip_analog;
5756352f7f91STakashi Iwai 
5757f873e536STakashi Iwai 	fill_pcm_stream_name(spec->stream_name_analog,
5758f873e536STakashi Iwai 			     sizeof(spec->stream_name_analog),
57597639a06cSTakashi Iwai 			     " Analog", codec->core.chip_name);
5760bbbc7e85STakashi Iwai 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5761bbbc7e85STakashi Iwai 	if (!info)
5762bbbc7e85STakashi Iwai 		return -ENOMEM;
5763bbbc7e85STakashi Iwai 	spec->pcm_rec[0] = info;
5764352f7f91STakashi Iwai 
5765352f7f91STakashi Iwai 	if (spec->multiout.num_dacs > 0) {
5766fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5767fb83b635STakashi Iwai 				 &pcm_analog_playback,
5768fb83b635STakashi Iwai 				 spec->stream_analog_playback,
5769fb83b635STakashi Iwai 				 spec->multiout.dac_nids[0]);
5770352f7f91STakashi Iwai 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5771352f7f91STakashi Iwai 			spec->multiout.max_channels;
5772352f7f91STakashi Iwai 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5773352f7f91STakashi Iwai 		    spec->autocfg.line_outs == 2)
5774352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5775352f7f91STakashi Iwai 				snd_pcm_2_1_chmaps;
5776352f7f91STakashi Iwai 	}
5777352f7f91STakashi Iwai 	if (spec->num_adc_nids) {
5778fb83b635STakashi Iwai 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5779fb83b635STakashi Iwai 				 (spec->dyn_adc_switch ?
5780fb83b635STakashi Iwai 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5781fb83b635STakashi Iwai 				 spec->stream_analog_capture,
5782fb83b635STakashi Iwai 				 spec->adc_nids[0]);
5783352f7f91STakashi Iwai 	}
5784352f7f91STakashi Iwai 
5785352f7f91STakashi Iwai  skip_analog:
5786352f7f91STakashi Iwai 	/* SPDIF for stream index #1 */
5787352f7f91STakashi Iwai 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5788f873e536STakashi Iwai 		fill_pcm_stream_name(spec->stream_name_digital,
5789352f7f91STakashi Iwai 				     sizeof(spec->stream_name_digital),
57907639a06cSTakashi Iwai 				     " Digital", codec->core.chip_name);
5791bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5792bbbc7e85STakashi Iwai 					     spec->stream_name_digital);
5793bbbc7e85STakashi Iwai 		if (!info)
5794bbbc7e85STakashi Iwai 			return -ENOMEM;
57959ab0cb30STakashi Iwai 		codec->follower_dig_outs = spec->multiout.follower_dig_outs;
5796bbbc7e85STakashi Iwai 		spec->pcm_rec[1] = info;
5797352f7f91STakashi Iwai 		if (spec->dig_out_type)
5798352f7f91STakashi Iwai 			info->pcm_type = spec->dig_out_type;
5799352f7f91STakashi Iwai 		else
5800352f7f91STakashi Iwai 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5801fb83b635STakashi Iwai 		if (spec->multiout.dig_out_nid)
5802fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5803fb83b635STakashi Iwai 					 &pcm_digital_playback,
5804fb83b635STakashi Iwai 					 spec->stream_digital_playback,
5805fb83b635STakashi Iwai 					 spec->multiout.dig_out_nid);
5806fb83b635STakashi Iwai 		if (spec->dig_in_nid)
5807fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5808fb83b635STakashi Iwai 					 &pcm_digital_capture,
5809fb83b635STakashi Iwai 					 spec->stream_digital_capture,
5810fb83b635STakashi Iwai 					 spec->dig_in_nid);
5811352f7f91STakashi Iwai 	}
5812352f7f91STakashi Iwai 
5813352f7f91STakashi Iwai 	if (spec->no_analog)
5814352f7f91STakashi Iwai 		return 0;
5815352f7f91STakashi Iwai 
5816352f7f91STakashi Iwai 	/* If the use of more than one ADC is requested for the current
5817352f7f91STakashi Iwai 	 * model, configure a second analog capture-only PCM.
5818352f7f91STakashi Iwai 	 */
5819352f7f91STakashi Iwai 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5820352f7f91STakashi Iwai 		!spec->dyn_adc_switch && !spec->auto_mic;
5821352f7f91STakashi Iwai 	/* Additional Analaog capture for index #2 */
5822352f7f91STakashi Iwai 	if (spec->alt_dac_nid || have_multi_adcs) {
5823a607148fSTakashi Iwai 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5824a607148fSTakashi Iwai 				     sizeof(spec->stream_name_alt_analog),
58257639a06cSTakashi Iwai 			     " Alt Analog", codec->core.chip_name);
5826bbbc7e85STakashi Iwai 		info = snd_hda_codec_pcm_new(codec, "%s",
5827bbbc7e85STakashi Iwai 					     spec->stream_name_alt_analog);
5828bbbc7e85STakashi Iwai 		if (!info)
5829bbbc7e85STakashi Iwai 			return -ENOMEM;
5830bbbc7e85STakashi Iwai 		spec->pcm_rec[2] = info;
5831fb83b635STakashi Iwai 		if (spec->alt_dac_nid)
5832fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5833fb83b635STakashi Iwai 					 &pcm_analog_alt_playback,
5834fb83b635STakashi Iwai 					 spec->stream_analog_alt_playback,
5835fb83b635STakashi Iwai 					 spec->alt_dac_nid);
5836fb83b635STakashi Iwai 		else
5837fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5838fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5839352f7f91STakashi Iwai 		if (have_multi_adcs) {
5840fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5841fb83b635STakashi Iwai 					 &pcm_analog_alt_capture,
5842fb83b635STakashi Iwai 					 spec->stream_analog_alt_capture,
5843fb83b635STakashi Iwai 					 spec->adc_nids[1]);
5844352f7f91STakashi Iwai 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5845352f7f91STakashi Iwai 				spec->num_adc_nids - 1;
5846352f7f91STakashi Iwai 		} else {
5847fb83b635STakashi Iwai 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5848fb83b635STakashi Iwai 					 &pcm_null_stream, NULL, 0);
5849352f7f91STakashi Iwai 		}
58501da177e4SLinus Torvalds 	}
58511da177e4SLinus Torvalds 
58521da177e4SLinus Torvalds 	return 0;
58531da177e4SLinus Torvalds }
58542698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5855352f7f91STakashi Iwai 
5856352f7f91STakashi Iwai 
5857352f7f91STakashi Iwai /*
5858352f7f91STakashi Iwai  * Standard auto-parser initializations
5859352f7f91STakashi Iwai  */
5860352f7f91STakashi Iwai 
5861d4156930STakashi Iwai /* configure the given path as a proper output */
58622c12c30dSTakashi Iwai static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5863352f7f91STakashi Iwai {
5864352f7f91STakashi Iwai 	struct nid_path *path;
5865d4156930STakashi Iwai 	hda_nid_t pin;
5866352f7f91STakashi Iwai 
5867196c1766STakashi Iwai 	path = snd_hda_get_path_from_idx(codec, path_idx);
5868d4156930STakashi Iwai 	if (!path || !path->depth)
5869352f7f91STakashi Iwai 		return;
5870d4156930STakashi Iwai 	pin = path->path[path->depth - 1];
58712c12c30dSTakashi Iwai 	restore_pin_ctl(codec, pin);
587265033cc8STakashi Iwai 	snd_hda_activate_path(codec, path, path->active,
587365033cc8STakashi Iwai 			      aamix_default(codec->spec));
5874e1284af7STakashi Iwai 	set_pin_eapd(codec, pin, path->active);
5875352f7f91STakashi Iwai }
5876352f7f91STakashi Iwai 
5877352f7f91STakashi Iwai /* initialize primary output paths */
5878352f7f91STakashi Iwai static void init_multi_out(struct hda_codec *codec)
5879352f7f91STakashi Iwai {
5880352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5881352f7f91STakashi Iwai 	int i;
5882352f7f91STakashi Iwai 
5883d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.line_outs; i++)
58842c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->out_paths[i]);
5885352f7f91STakashi Iwai }
5886352f7f91STakashi Iwai 
5887db23fd19STakashi Iwai 
58882c12c30dSTakashi Iwai static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5889352f7f91STakashi Iwai {
5890352f7f91STakashi Iwai 	int i;
5891352f7f91STakashi Iwai 
5892d4156930STakashi Iwai 	for (i = 0; i < num_outs; i++)
58932c12c30dSTakashi Iwai 		set_output_and_unmute(codec, paths[i]);
5894352f7f91STakashi Iwai }
5895db23fd19STakashi Iwai 
5896db23fd19STakashi Iwai /* initialize hp and speaker paths */
5897db23fd19STakashi Iwai static void init_extra_out(struct hda_codec *codec)
5898db23fd19STakashi Iwai {
5899db23fd19STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5900db23fd19STakashi Iwai 
5901db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
59022c12c30dSTakashi Iwai 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5903db23fd19STakashi Iwai 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5904db23fd19STakashi Iwai 		__init_extra_out(codec, spec->autocfg.speaker_outs,
59052c12c30dSTakashi Iwai 				 spec->speaker_paths);
5906352f7f91STakashi Iwai }
5907352f7f91STakashi Iwai 
5908352f7f91STakashi Iwai /* initialize multi-io paths */
5909352f7f91STakashi Iwai static void init_multi_io(struct hda_codec *codec)
5910352f7f91STakashi Iwai {
5911352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5912352f7f91STakashi Iwai 	int i;
5913352f7f91STakashi Iwai 
5914352f7f91STakashi Iwai 	for (i = 0; i < spec->multi_ios; i++) {
5915352f7f91STakashi Iwai 		hda_nid_t pin = spec->multi_io[i].pin;
5916352f7f91STakashi Iwai 		struct nid_path *path;
5917196c1766STakashi Iwai 		path = get_multiio_path(codec, i);
5918352f7f91STakashi Iwai 		if (!path)
5919352f7f91STakashi Iwai 			continue;
5920352f7f91STakashi Iwai 		if (!spec->multi_io[i].ctl_in)
5921352f7f91STakashi Iwai 			spec->multi_io[i].ctl_in =
59222c12c30dSTakashi Iwai 				snd_hda_codec_get_pin_target(codec, pin);
592365033cc8STakashi Iwai 		snd_hda_activate_path(codec, path, path->active,
592465033cc8STakashi Iwai 				      aamix_default(spec));
5925352f7f91STakashi Iwai 	}
5926352f7f91STakashi Iwai }
5927352f7f91STakashi Iwai 
59284f7f67fbSTakashi Iwai static void init_aamix_paths(struct hda_codec *codec)
59294f7f67fbSTakashi Iwai {
59304f7f67fbSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
59314f7f67fbSTakashi Iwai 
59324f7f67fbSTakashi Iwai 	if (!spec->have_aamix_ctl)
59334f7f67fbSTakashi Iwai 		return;
5934e7fdd527STakashi Iwai 	if (!has_aamix_out_paths(spec))
5935e7fdd527STakashi Iwai 		return;
59364f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
59374f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[0],
59384f7f67fbSTakashi Iwai 			   spec->autocfg.line_out_type);
59394f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
59404f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[1],
59414f7f67fbSTakashi Iwai 			   AUTO_PIN_HP_OUT);
59424f7f67fbSTakashi Iwai 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
59434f7f67fbSTakashi Iwai 			   spec->aamix_out_paths[2],
59444f7f67fbSTakashi Iwai 			   AUTO_PIN_SPEAKER_OUT);
59454f7f67fbSTakashi Iwai }
59464f7f67fbSTakashi Iwai 
5947352f7f91STakashi Iwai /* set up input pins and loopback paths */
5948352f7f91STakashi Iwai static void init_analog_input(struct hda_codec *codec)
5949352f7f91STakashi Iwai {
5950352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5951352f7f91STakashi Iwai 	struct auto_pin_cfg *cfg = &spec->autocfg;
5952352f7f91STakashi Iwai 	int i;
5953352f7f91STakashi Iwai 
5954352f7f91STakashi Iwai 	for (i = 0; i < cfg->num_inputs; i++) {
5955352f7f91STakashi Iwai 		hda_nid_t nid = cfg->inputs[i].pin;
5956352f7f91STakashi Iwai 		if (is_input_pin(codec, nid))
59572c12c30dSTakashi Iwai 			restore_pin_ctl(codec, nid);
5958352f7f91STakashi Iwai 
5959352f7f91STakashi Iwai 		/* init loopback inputs */
5960352f7f91STakashi Iwai 		if (spec->mixer_nid) {
59613e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_paths[i]);
59623e367f15STakashi Iwai 			resume_path_from_idx(codec, spec->loopback_merge_path);
5963352f7f91STakashi Iwai 		}
5964352f7f91STakashi Iwai 	}
5965352f7f91STakashi Iwai }
5966352f7f91STakashi Iwai 
5967352f7f91STakashi Iwai /* initialize ADC paths */
5968352f7f91STakashi Iwai static void init_input_src(struct hda_codec *codec)
5969352f7f91STakashi Iwai {
5970352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
5971352f7f91STakashi Iwai 	struct hda_input_mux *imux = &spec->input_mux;
5972352f7f91STakashi Iwai 	struct nid_path *path;
5973352f7f91STakashi Iwai 	int i, c, nums;
5974352f7f91STakashi Iwai 
5975352f7f91STakashi Iwai 	if (spec->dyn_adc_switch)
5976352f7f91STakashi Iwai 		nums = 1;
5977352f7f91STakashi Iwai 	else
5978352f7f91STakashi Iwai 		nums = spec->num_adc_nids;
5979352f7f91STakashi Iwai 
5980352f7f91STakashi Iwai 	for (c = 0; c < nums; c++) {
5981352f7f91STakashi Iwai 		for (i = 0; i < imux->num_items; i++) {
5982c697b716STakashi Iwai 			path = get_input_path(codec, c, i);
5983352f7f91STakashi Iwai 			if (path) {
5984352f7f91STakashi Iwai 				bool active = path->active;
5985352f7f91STakashi Iwai 				if (i == spec->cur_mux[c])
5986352f7f91STakashi Iwai 					active = true;
5987352f7f91STakashi Iwai 				snd_hda_activate_path(codec, path, active, false);
5988352f7f91STakashi Iwai 			}
5989352f7f91STakashi Iwai 		}
5990967303daSTakashi Iwai 		if (spec->hp_mic)
5991967303daSTakashi Iwai 			update_hp_mic(codec, c, true);
5992352f7f91STakashi Iwai 	}
5993352f7f91STakashi Iwai 
5994352f7f91STakashi Iwai 	if (spec->cap_sync_hook)
59957fe30711STakashi Iwai 		spec->cap_sync_hook(codec, NULL, NULL);
5996352f7f91STakashi Iwai }
5997352f7f91STakashi Iwai 
5998352f7f91STakashi Iwai /* set right pin controls for digital I/O */
5999352f7f91STakashi Iwai static void init_digital(struct hda_codec *codec)
6000352f7f91STakashi Iwai {
6001352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6002352f7f91STakashi Iwai 	int i;
6003352f7f91STakashi Iwai 	hda_nid_t pin;
6004352f7f91STakashi Iwai 
6005d4156930STakashi Iwai 	for (i = 0; i < spec->autocfg.dig_outs; i++)
60062c12c30dSTakashi Iwai 		set_output_and_unmute(codec, spec->digout_paths[i]);
6007352f7f91STakashi Iwai 	pin = spec->autocfg.dig_in_pin;
60082430d7b7STakashi Iwai 	if (pin) {
60092c12c30dSTakashi Iwai 		restore_pin_ctl(codec, pin);
60103e367f15STakashi Iwai 		resume_path_from_idx(codec, spec->digin_path);
60112430d7b7STakashi Iwai 	}
6012352f7f91STakashi Iwai }
6013352f7f91STakashi Iwai 
6014973e4972STakashi Iwai /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
6015973e4972STakashi Iwai  * invalid unsol tags by some reason
6016973e4972STakashi Iwai  */
6017973e4972STakashi Iwai static void clear_unsol_on_unused_pins(struct hda_codec *codec)
6018973e4972STakashi Iwai {
6019a9c2dfc8STakashi Iwai 	const struct hda_pincfg *pin;
6020973e4972STakashi Iwai 	int i;
6021973e4972STakashi Iwai 
6022a9c2dfc8STakashi Iwai 	snd_array_for_each(&codec->init_pins, i, pin) {
6023973e4972STakashi Iwai 		hda_nid_t nid = pin->nid;
6024973e4972STakashi Iwai 		if (is_jack_detectable(codec, nid) &&
6025973e4972STakashi Iwai 		    !snd_hda_jack_tbl_get(codec, nid))
6026401caff7STakashi Iwai 			snd_hda_codec_write_cache(codec, nid, 0,
6027973e4972STakashi Iwai 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
6028973e4972STakashi Iwai 	}
6029973e4972STakashi Iwai }
6030973e4972STakashi Iwai 
6031dda42bd0STakashi Iwai /**
6032dda42bd0STakashi Iwai  * snd_hda_gen_init - initialize the generic spec
6033dda42bd0STakashi Iwai  * @codec: the HDA codec
6034dda42bd0STakashi Iwai  *
6035dda42bd0STakashi Iwai  * This can be put as patch_ops init function.
60365187ac16STakashi Iwai  */
6037352f7f91STakashi Iwai int snd_hda_gen_init(struct hda_codec *codec)
6038352f7f91STakashi Iwai {
6039352f7f91STakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6040352f7f91STakashi Iwai 
6041352f7f91STakashi Iwai 	if (spec->init_hook)
6042352f7f91STakashi Iwai 		spec->init_hook(codec);
6043352f7f91STakashi Iwai 
604489781d08STakashi Iwai 	if (!spec->skip_verbs)
6045352f7f91STakashi Iwai 		snd_hda_apply_verbs(codec);
6046352f7f91STakashi Iwai 
6047352f7f91STakashi Iwai 	init_multi_out(codec);
6048352f7f91STakashi Iwai 	init_extra_out(codec);
6049352f7f91STakashi Iwai 	init_multi_io(codec);
60504f7f67fbSTakashi Iwai 	init_aamix_paths(codec);
6051352f7f91STakashi Iwai 	init_analog_input(codec);
6052352f7f91STakashi Iwai 	init_input_src(codec);
6053352f7f91STakashi Iwai 	init_digital(codec);
6054352f7f91STakashi Iwai 
6055973e4972STakashi Iwai 	clear_unsol_on_unused_pins(codec);
6056973e4972STakashi Iwai 
6057e6feb5d0STakashi Iwai 	sync_all_pin_power_ctls(codec);
6058e6feb5d0STakashi Iwai 
6059352f7f91STakashi Iwai 	/* call init functions of standard auto-mute helpers */
6060a5cc2509STakashi Iwai 	update_automute_all(codec);
6061352f7f91STakashi Iwai 
60621a462be5STakashi Iwai 	snd_hda_regmap_sync(codec);
60633bbcd274STakashi Iwai 
6064352f7f91STakashi Iwai 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
6065352f7f91STakashi Iwai 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
6066352f7f91STakashi Iwai 
6067352f7f91STakashi Iwai 	hda_call_check_power_status(codec, 0x01);
6068352f7f91STakashi Iwai 	return 0;
6069352f7f91STakashi Iwai }
60702698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_init);
6071fce52a3bSTakashi Iwai 
6072dda42bd0STakashi Iwai /**
6073dda42bd0STakashi Iwai  * snd_hda_gen_free - free the generic spec
6074dda42bd0STakashi Iwai  * @codec: the HDA codec
6075dda42bd0STakashi Iwai  *
6076dda42bd0STakashi Iwai  * This can be put as patch_ops free function.
60775187ac16STakashi Iwai  */
6078fce52a3bSTakashi Iwai void snd_hda_gen_free(struct hda_codec *codec)
6079fce52a3bSTakashi Iwai {
60808a02c0ccSTakashi Iwai 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
6081fce52a3bSTakashi Iwai 	snd_hda_gen_spec_free(codec->spec);
6082fce52a3bSTakashi Iwai 	kfree(codec->spec);
6083fce52a3bSTakashi Iwai 	codec->spec = NULL;
6084fce52a3bSTakashi Iwai }
60852698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_free);
6086fce52a3bSTakashi Iwai 
6087dda42bd0STakashi Iwai /**
6088dda42bd0STakashi Iwai  * snd_hda_gen_check_power_status - check the loopback power save state
6089dda42bd0STakashi Iwai  * @codec: the HDA codec
6090dda42bd0STakashi Iwai  * @nid: NID to inspect
6091dda42bd0STakashi Iwai  *
6092dda42bd0STakashi Iwai  * This can be put as patch_ops check_power_status function.
60935187ac16STakashi Iwai  */
6094fce52a3bSTakashi Iwai int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
6095fce52a3bSTakashi Iwai {
6096fce52a3bSTakashi Iwai 	struct hda_gen_spec *spec = codec->spec;
6097fce52a3bSTakashi Iwai 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
6098fce52a3bSTakashi Iwai }
60992698ea98STakashi Iwai EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
6100352f7f91STakashi Iwai 
6101352f7f91STakashi Iwai 
6102352f7f91STakashi Iwai /*
6103352f7f91STakashi Iwai  * the generic codec support
6104352f7f91STakashi Iwai  */
61051da177e4SLinus Torvalds 
6106352f7f91STakashi Iwai static const struct hda_codec_ops generic_patch_ops = {
6107352f7f91STakashi Iwai 	.build_controls = snd_hda_gen_build_controls,
6108352f7f91STakashi Iwai 	.build_pcms = snd_hda_gen_build_pcms,
6109352f7f91STakashi Iwai 	.init = snd_hda_gen_init,
6110fce52a3bSTakashi Iwai 	.free = snd_hda_gen_free,
6111352f7f91STakashi Iwai 	.unsol_event = snd_hda_jack_unsol_event,
6112fce52a3bSTakashi Iwai 	.check_power_status = snd_hda_gen_check_power_status,
61131da177e4SLinus Torvalds };
61141da177e4SLinus Torvalds 
6115d8a766a1STakashi Iwai /*
6116dda42bd0STakashi Iwai  * snd_hda_parse_generic_codec - Generic codec parser
6117dda42bd0STakashi Iwai  * @codec: the HDA codec
6118dda42bd0STakashi Iwai  */
6119d8a766a1STakashi Iwai static int snd_hda_parse_generic_codec(struct hda_codec *codec)
61201da177e4SLinus Torvalds {
6121352f7f91STakashi Iwai 	struct hda_gen_spec *spec;
61221da177e4SLinus Torvalds 	int err;
61231da177e4SLinus Torvalds 
6124e560d8d8STakashi Iwai 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6125352f7f91STakashi Iwai 	if (!spec)
61261da177e4SLinus Torvalds 		return -ENOMEM;
6127352f7f91STakashi Iwai 	snd_hda_gen_spec_init(spec);
61281da177e4SLinus Torvalds 	codec->spec = spec;
61291da177e4SLinus Torvalds 
61309eb413e5STakashi Iwai 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
61319eb413e5STakashi Iwai 	if (err < 0)
6132cfef67f0SWenwen Wang 		goto error;
61339eb413e5STakashi Iwai 
61349eb413e5STakashi Iwai 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
6135352f7f91STakashi Iwai 	if (err < 0)
61361da177e4SLinus Torvalds 		goto error;
61371da177e4SLinus Torvalds 
61381da177e4SLinus Torvalds 	codec->patch_ops = generic_patch_ops;
61391da177e4SLinus Torvalds 	return 0;
61401da177e4SLinus Torvalds 
61411da177e4SLinus Torvalds error:
6142fce52a3bSTakashi Iwai 	snd_hda_gen_free(codec);
61431da177e4SLinus Torvalds 	return err;
61441da177e4SLinus Torvalds }
6145d8a766a1STakashi Iwai 
6146b9a94a9cSTakashi Iwai static const struct hda_device_id snd_hda_id_generic[] = {
6147b9a94a9cSTakashi Iwai 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
6148d8a766a1STakashi Iwai 	{} /* terminator */
6149d8a766a1STakashi Iwai };
6150b9a94a9cSTakashi Iwai MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
6151d8a766a1STakashi Iwai 
6152d8a766a1STakashi Iwai static struct hda_codec_driver generic_driver = {
6153b9a94a9cSTakashi Iwai 	.id = snd_hda_id_generic,
6154d8a766a1STakashi Iwai };
6155d8a766a1STakashi Iwai 
6156d8a766a1STakashi Iwai module_hda_codec_driver(generic_driver);
6157b21bdd0dSTakashi Iwai 
6158b21bdd0dSTakashi Iwai MODULE_LICENSE("GPL");
6159b21bdd0dSTakashi Iwai MODULE_DESCRIPTION("Generic HD-audio codec parser");
6160