xref: /OK3568_Linux_fs/kernel/sound/pci/hda/hda_generic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Universal Interface for Intel High Definition Audio Codec
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Generic widget tree parser
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/export.h>
13*4882a593Smuzhiyun #include <linux/sort.h>
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/ctype.h>
16*4882a593Smuzhiyun #include <linux/string.h>
17*4882a593Smuzhiyun #include <linux/bitops.h>
18*4882a593Smuzhiyun #include <linux/module.h>
19*4882a593Smuzhiyun #include <linux/leds.h>
20*4882a593Smuzhiyun #include <sound/core.h>
21*4882a593Smuzhiyun #include <sound/jack.h>
22*4882a593Smuzhiyun #include <sound/tlv.h>
23*4882a593Smuzhiyun #include <sound/hda_codec.h>
24*4882a593Smuzhiyun #include "hda_local.h"
25*4882a593Smuzhiyun #include "hda_auto_parser.h"
26*4882a593Smuzhiyun #include "hda_jack.h"
27*4882a593Smuzhiyun #include "hda_beep.h"
28*4882a593Smuzhiyun #include "hda_generic.h"
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /**
32*4882a593Smuzhiyun  * snd_hda_gen_spec_init - initialize hda_gen_spec struct
33*4882a593Smuzhiyun  * @spec: hda_gen_spec object to initialize
34*4882a593Smuzhiyun  *
35*4882a593Smuzhiyun  * Initialize the given hda_gen_spec object.
36*4882a593Smuzhiyun  */
snd_hda_gen_spec_init(struct hda_gen_spec * spec)37*4882a593Smuzhiyun int snd_hda_gen_spec_init(struct hda_gen_spec *spec)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
40*4882a593Smuzhiyun 	snd_array_init(&spec->paths, sizeof(struct nid_path), 8);
41*4882a593Smuzhiyun 	snd_array_init(&spec->loopback_list, sizeof(struct hda_amp_list), 8);
42*4882a593Smuzhiyun 	mutex_init(&spec->pcm_mutex);
43*4882a593Smuzhiyun 	return 0;
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_spec_init);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /**
48*4882a593Smuzhiyun  * snd_hda_gen_add_kctl - Add a new kctl_new struct from the template
49*4882a593Smuzhiyun  * @spec: hda_gen_spec object
50*4882a593Smuzhiyun  * @name: name string to override the template, NULL if unchanged
51*4882a593Smuzhiyun  * @temp: template for the new kctl
52*4882a593Smuzhiyun  *
53*4882a593Smuzhiyun  * Add a new kctl (actually snd_kcontrol_new to be instantiated later)
54*4882a593Smuzhiyun  * element based on the given snd_kcontrol_new template @temp and the
55*4882a593Smuzhiyun  * name string @name to the list in @spec.
56*4882a593Smuzhiyun  * Returns the newly created object or NULL as error.
57*4882a593Smuzhiyun  */
58*4882a593Smuzhiyun struct snd_kcontrol_new *
snd_hda_gen_add_kctl(struct hda_gen_spec * spec,const char * name,const struct snd_kcontrol_new * temp)59*4882a593Smuzhiyun snd_hda_gen_add_kctl(struct hda_gen_spec *spec, const char *name,
60*4882a593Smuzhiyun 		     const struct snd_kcontrol_new *temp)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew = snd_array_new(&spec->kctls);
63*4882a593Smuzhiyun 	if (!knew)
64*4882a593Smuzhiyun 		return NULL;
65*4882a593Smuzhiyun 	*knew = *temp;
66*4882a593Smuzhiyun 	if (name)
67*4882a593Smuzhiyun 		knew->name = kstrdup(name, GFP_KERNEL);
68*4882a593Smuzhiyun 	else if (knew->name)
69*4882a593Smuzhiyun 		knew->name = kstrdup(knew->name, GFP_KERNEL);
70*4882a593Smuzhiyun 	if (!knew->name)
71*4882a593Smuzhiyun 		return NULL;
72*4882a593Smuzhiyun 	return knew;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_add_kctl);
75*4882a593Smuzhiyun 
free_kctls(struct hda_gen_spec * spec)76*4882a593Smuzhiyun static void free_kctls(struct hda_gen_spec *spec)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	if (spec->kctls.list) {
79*4882a593Smuzhiyun 		struct snd_kcontrol_new *kctl = spec->kctls.list;
80*4882a593Smuzhiyun 		int i;
81*4882a593Smuzhiyun 		for (i = 0; i < spec->kctls.used; i++)
82*4882a593Smuzhiyun 			kfree(kctl[i].name);
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 	snd_array_free(&spec->kctls);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
snd_hda_gen_spec_free(struct hda_gen_spec * spec)87*4882a593Smuzhiyun static void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun 	if (!spec)
90*4882a593Smuzhiyun 		return;
91*4882a593Smuzhiyun 	free_kctls(spec);
92*4882a593Smuzhiyun 	snd_array_free(&spec->paths);
93*4882a593Smuzhiyun 	snd_array_free(&spec->loopback_list);
94*4882a593Smuzhiyun #ifdef CONFIG_SND_HDA_GENERIC_LEDS
95*4882a593Smuzhiyun 	if (spec->led_cdevs[LED_AUDIO_MUTE])
96*4882a593Smuzhiyun 		led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MUTE]);
97*4882a593Smuzhiyun 	if (spec->led_cdevs[LED_AUDIO_MICMUTE])
98*4882a593Smuzhiyun 		led_classdev_unregister(spec->led_cdevs[LED_AUDIO_MICMUTE]);
99*4882a593Smuzhiyun #endif
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun  * store user hints
104*4882a593Smuzhiyun  */
parse_user_hints(struct hda_codec * codec)105*4882a593Smuzhiyun static void parse_user_hints(struct hda_codec *codec)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
108*4882a593Smuzhiyun 	int val;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "jack_detect");
111*4882a593Smuzhiyun 	if (val >= 0)
112*4882a593Smuzhiyun 		codec->no_jack_detect = !val;
113*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "inv_jack_detect");
114*4882a593Smuzhiyun 	if (val >= 0)
115*4882a593Smuzhiyun 		codec->inv_jack_detect = !!val;
116*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "trigger_sense");
117*4882a593Smuzhiyun 	if (val >= 0)
118*4882a593Smuzhiyun 		codec->no_trigger_sense = !val;
119*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "inv_eapd");
120*4882a593Smuzhiyun 	if (val >= 0)
121*4882a593Smuzhiyun 		codec->inv_eapd = !!val;
122*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "pcm_format_first");
123*4882a593Smuzhiyun 	if (val >= 0)
124*4882a593Smuzhiyun 		codec->pcm_format_first = !!val;
125*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "sticky_stream");
126*4882a593Smuzhiyun 	if (val >= 0)
127*4882a593Smuzhiyun 		codec->no_sticky_stream = !val;
128*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "spdif_status_reset");
129*4882a593Smuzhiyun 	if (val >= 0)
130*4882a593Smuzhiyun 		codec->spdif_status_reset = !!val;
131*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "pin_amp_workaround");
132*4882a593Smuzhiyun 	if (val >= 0)
133*4882a593Smuzhiyun 		codec->pin_amp_workaround = !!val;
134*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "single_adc_amp");
135*4882a593Smuzhiyun 	if (val >= 0)
136*4882a593Smuzhiyun 		codec->single_adc_amp = !!val;
137*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "power_save_node");
138*4882a593Smuzhiyun 	if (val >= 0)
139*4882a593Smuzhiyun 		codec->power_save_node = !!val;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "auto_mute");
142*4882a593Smuzhiyun 	if (val >= 0)
143*4882a593Smuzhiyun 		spec->suppress_auto_mute = !val;
144*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "auto_mic");
145*4882a593Smuzhiyun 	if (val >= 0)
146*4882a593Smuzhiyun 		spec->suppress_auto_mic = !val;
147*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "line_in_auto_switch");
148*4882a593Smuzhiyun 	if (val >= 0)
149*4882a593Smuzhiyun 		spec->line_in_auto_switch = !!val;
150*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "auto_mute_via_amp");
151*4882a593Smuzhiyun 	if (val >= 0)
152*4882a593Smuzhiyun 		spec->auto_mute_via_amp = !!val;
153*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "need_dac_fix");
154*4882a593Smuzhiyun 	if (val >= 0)
155*4882a593Smuzhiyun 		spec->need_dac_fix = !!val;
156*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "primary_hp");
157*4882a593Smuzhiyun 	if (val >= 0)
158*4882a593Smuzhiyun 		spec->no_primary_hp = !val;
159*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "multi_io");
160*4882a593Smuzhiyun 	if (val >= 0)
161*4882a593Smuzhiyun 		spec->no_multi_io = !val;
162*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "multi_cap_vol");
163*4882a593Smuzhiyun 	if (val >= 0)
164*4882a593Smuzhiyun 		spec->multi_cap_vol = !!val;
165*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "inv_dmic_split");
166*4882a593Smuzhiyun 	if (val >= 0)
167*4882a593Smuzhiyun 		spec->inv_dmic_split = !!val;
168*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "indep_hp");
169*4882a593Smuzhiyun 	if (val >= 0)
170*4882a593Smuzhiyun 		spec->indep_hp = !!val;
171*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "add_stereo_mix_input");
172*4882a593Smuzhiyun 	if (val >= 0)
173*4882a593Smuzhiyun 		spec->add_stereo_mix_input = !!val;
174*4882a593Smuzhiyun 	/* the following two are just for compatibility */
175*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "add_out_jack_modes");
176*4882a593Smuzhiyun 	if (val >= 0)
177*4882a593Smuzhiyun 		spec->add_jack_modes = !!val;
178*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "add_in_jack_modes");
179*4882a593Smuzhiyun 	if (val >= 0)
180*4882a593Smuzhiyun 		spec->add_jack_modes = !!val;
181*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "add_jack_modes");
182*4882a593Smuzhiyun 	if (val >= 0)
183*4882a593Smuzhiyun 		spec->add_jack_modes = !!val;
184*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "power_down_unused");
185*4882a593Smuzhiyun 	if (val >= 0)
186*4882a593Smuzhiyun 		spec->power_down_unused = !!val;
187*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "add_hp_mic");
188*4882a593Smuzhiyun 	if (val >= 0)
189*4882a593Smuzhiyun 		spec->hp_mic = !!val;
190*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "hp_mic_detect");
191*4882a593Smuzhiyun 	if (val >= 0)
192*4882a593Smuzhiyun 		spec->suppress_hp_mic_detect = !val;
193*4882a593Smuzhiyun 	val = snd_hda_get_bool_hint(codec, "vmaster");
194*4882a593Smuzhiyun 	if (val >= 0)
195*4882a593Smuzhiyun 		spec->suppress_vmaster = !val;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	if (!snd_hda_get_int_hint(codec, "mixer_nid", &val))
198*4882a593Smuzhiyun 		spec->mixer_nid = val;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun  * pin control value accesses
203*4882a593Smuzhiyun  */
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun #define update_pin_ctl(codec, pin, val) \
206*4882a593Smuzhiyun 	snd_hda_codec_write_cache(codec, pin, 0, \
207*4882a593Smuzhiyun 				   AC_VERB_SET_PIN_WIDGET_CONTROL, val)
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun /* restore the pinctl based on the cached value */
restore_pin_ctl(struct hda_codec * codec,hda_nid_t pin)210*4882a593Smuzhiyun static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun 	update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun /* set the pinctl target value and write it if requested */
set_pin_target(struct hda_codec * codec,hda_nid_t pin,unsigned int val,bool do_write)216*4882a593Smuzhiyun static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
217*4882a593Smuzhiyun 			   unsigned int val, bool do_write)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun 	if (!pin)
220*4882a593Smuzhiyun 		return;
221*4882a593Smuzhiyun 	val = snd_hda_correct_pin_ctl(codec, pin, val);
222*4882a593Smuzhiyun 	snd_hda_codec_set_pin_target(codec, pin, val);
223*4882a593Smuzhiyun 	if (do_write)
224*4882a593Smuzhiyun 		update_pin_ctl(codec, pin, val);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun /* set pinctl target values for all given pins */
set_pin_targets(struct hda_codec * codec,int num_pins,hda_nid_t * pins,unsigned int val)228*4882a593Smuzhiyun static void set_pin_targets(struct hda_codec *codec, int num_pins,
229*4882a593Smuzhiyun 			    hda_nid_t *pins, unsigned int val)
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun 	int i;
232*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++)
233*4882a593Smuzhiyun 		set_pin_target(codec, pins[i], val, false);
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /*
237*4882a593Smuzhiyun  * parsing paths
238*4882a593Smuzhiyun  */
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun /* return the position of NID in the list, or -1 if not found */
find_idx_in_nid_list(hda_nid_t nid,const hda_nid_t * list,int nums)241*4882a593Smuzhiyun static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	int i;
244*4882a593Smuzhiyun 	for (i = 0; i < nums; i++)
245*4882a593Smuzhiyun 		if (list[i] == nid)
246*4882a593Smuzhiyun 			return i;
247*4882a593Smuzhiyun 	return -1;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun /* return true if the given NID is contained in the path */
is_nid_contained(struct nid_path * path,hda_nid_t nid)251*4882a593Smuzhiyun static bool is_nid_contained(struct nid_path *path, hda_nid_t nid)
252*4882a593Smuzhiyun {
253*4882a593Smuzhiyun 	return find_idx_in_nid_list(nid, path->path, path->depth) >= 0;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
get_nid_path(struct hda_codec * codec,hda_nid_t from_nid,hda_nid_t to_nid,int anchor_nid)256*4882a593Smuzhiyun static struct nid_path *get_nid_path(struct hda_codec *codec,
257*4882a593Smuzhiyun 				     hda_nid_t from_nid, hda_nid_t to_nid,
258*4882a593Smuzhiyun 				     int anchor_nid)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
261*4882a593Smuzhiyun 	struct nid_path *path;
262*4882a593Smuzhiyun 	int i;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	snd_array_for_each(&spec->paths, i, path) {
265*4882a593Smuzhiyun 		if (path->depth <= 0)
266*4882a593Smuzhiyun 			continue;
267*4882a593Smuzhiyun 		if ((!from_nid || path->path[0] == from_nid) &&
268*4882a593Smuzhiyun 		    (!to_nid || path->path[path->depth - 1] == to_nid)) {
269*4882a593Smuzhiyun 			if (!anchor_nid ||
270*4882a593Smuzhiyun 			    (anchor_nid > 0 && is_nid_contained(path, anchor_nid)) ||
271*4882a593Smuzhiyun 			    (anchor_nid < 0 && !is_nid_contained(path, anchor_nid)))
272*4882a593Smuzhiyun 				return path;
273*4882a593Smuzhiyun 		}
274*4882a593Smuzhiyun 	}
275*4882a593Smuzhiyun 	return NULL;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun /**
279*4882a593Smuzhiyun  * snd_hda_get_path_idx - get the index number corresponding to the path
280*4882a593Smuzhiyun  * instance
281*4882a593Smuzhiyun  * @codec: the HDA codec
282*4882a593Smuzhiyun  * @path: nid_path object
283*4882a593Smuzhiyun  *
284*4882a593Smuzhiyun  * The returned index starts from 1, i.e. the actual array index with offset 1,
285*4882a593Smuzhiyun  * and zero is handled as an invalid path
286*4882a593Smuzhiyun  */
snd_hda_get_path_idx(struct hda_codec * codec,struct nid_path * path)287*4882a593Smuzhiyun int snd_hda_get_path_idx(struct hda_codec *codec, struct nid_path *path)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
290*4882a593Smuzhiyun 	struct nid_path *array = spec->paths.list;
291*4882a593Smuzhiyun 	ssize_t idx;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (!spec->paths.used)
294*4882a593Smuzhiyun 		return 0;
295*4882a593Smuzhiyun 	idx = path - array;
296*4882a593Smuzhiyun 	if (idx < 0 || idx >= spec->paths.used)
297*4882a593Smuzhiyun 		return 0;
298*4882a593Smuzhiyun 	return idx + 1;
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_get_path_idx);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun /**
303*4882a593Smuzhiyun  * snd_hda_get_path_from_idx - get the path instance corresponding to the
304*4882a593Smuzhiyun  * given index number
305*4882a593Smuzhiyun  * @codec: the HDA codec
306*4882a593Smuzhiyun  * @idx: the path index
307*4882a593Smuzhiyun  */
snd_hda_get_path_from_idx(struct hda_codec * codec,int idx)308*4882a593Smuzhiyun struct nid_path *snd_hda_get_path_from_idx(struct hda_codec *codec, int idx)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if (idx <= 0 || idx > spec->paths.used)
313*4882a593Smuzhiyun 		return NULL;
314*4882a593Smuzhiyun 	return snd_array_elem(&spec->paths, idx - 1);
315*4882a593Smuzhiyun }
316*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_get_path_from_idx);
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun /* check whether the given DAC is already found in any existing paths */
is_dac_already_used(struct hda_codec * codec,hda_nid_t nid)319*4882a593Smuzhiyun static bool is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
322*4882a593Smuzhiyun 	const struct nid_path *path;
323*4882a593Smuzhiyun 	int i;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	snd_array_for_each(&spec->paths, i, path) {
326*4882a593Smuzhiyun 		if (path->path[0] == nid)
327*4882a593Smuzhiyun 			return true;
328*4882a593Smuzhiyun 	}
329*4882a593Smuzhiyun 	return false;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun /* check whether the given two widgets can be connected */
is_reachable_path(struct hda_codec * codec,hda_nid_t from_nid,hda_nid_t to_nid)333*4882a593Smuzhiyun static bool is_reachable_path(struct hda_codec *codec,
334*4882a593Smuzhiyun 			      hda_nid_t from_nid, hda_nid_t to_nid)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun 	if (!from_nid || !to_nid)
337*4882a593Smuzhiyun 		return false;
338*4882a593Smuzhiyun 	return snd_hda_get_conn_index(codec, to_nid, from_nid, true) >= 0;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun /* nid, dir and idx */
342*4882a593Smuzhiyun #define AMP_VAL_COMPARE_MASK	(0xffff | (1U << 18) | (0x0f << 19))
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun /* check whether the given ctl is already assigned in any path elements */
is_ctl_used(struct hda_codec * codec,unsigned int val,int type)345*4882a593Smuzhiyun static bool is_ctl_used(struct hda_codec *codec, unsigned int val, int type)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
348*4882a593Smuzhiyun 	const struct nid_path *path;
349*4882a593Smuzhiyun 	int i;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	val &= AMP_VAL_COMPARE_MASK;
352*4882a593Smuzhiyun 	snd_array_for_each(&spec->paths, i, path) {
353*4882a593Smuzhiyun 		if ((path->ctls[type] & AMP_VAL_COMPARE_MASK) == val)
354*4882a593Smuzhiyun 			return true;
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun 	return false;
357*4882a593Smuzhiyun }
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun /* check whether a control with the given (nid, dir, idx) was assigned */
is_ctl_associated(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,int type)360*4882a593Smuzhiyun static bool is_ctl_associated(struct hda_codec *codec, hda_nid_t nid,
361*4882a593Smuzhiyun 			      int dir, int idx, int type)
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	unsigned int val = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir);
364*4882a593Smuzhiyun 	return is_ctl_used(codec, val, type);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun 
print_nid_path(struct hda_codec * codec,const char * pfx,struct nid_path * path)367*4882a593Smuzhiyun static void print_nid_path(struct hda_codec *codec,
368*4882a593Smuzhiyun 			   const char *pfx, struct nid_path *path)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	char buf[40];
371*4882a593Smuzhiyun 	char *pos = buf;
372*4882a593Smuzhiyun 	int i;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	*pos = 0;
375*4882a593Smuzhiyun 	for (i = 0; i < path->depth; i++)
376*4882a593Smuzhiyun 		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
377*4882a593Smuzhiyun 				 pos != buf ? ":" : "",
378*4882a593Smuzhiyun 				 path->path[i]);
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun /* called recursively */
__parse_nid_path(struct hda_codec * codec,hda_nid_t from_nid,hda_nid_t to_nid,int anchor_nid,struct nid_path * path,int depth)384*4882a593Smuzhiyun static bool __parse_nid_path(struct hda_codec *codec,
385*4882a593Smuzhiyun 			     hda_nid_t from_nid, hda_nid_t to_nid,
386*4882a593Smuzhiyun 			     int anchor_nid, struct nid_path *path,
387*4882a593Smuzhiyun 			     int depth)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun 	const hda_nid_t *conn;
390*4882a593Smuzhiyun 	int i, nums;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	if (to_nid == anchor_nid)
393*4882a593Smuzhiyun 		anchor_nid = 0; /* anchor passed */
394*4882a593Smuzhiyun 	else if (to_nid == (hda_nid_t)(-anchor_nid))
395*4882a593Smuzhiyun 		return false; /* hit the exclusive nid */
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	nums = snd_hda_get_conn_list(codec, to_nid, &conn);
398*4882a593Smuzhiyun 	for (i = 0; i < nums; i++) {
399*4882a593Smuzhiyun 		if (conn[i] != from_nid) {
400*4882a593Smuzhiyun 			/* special case: when from_nid is 0,
401*4882a593Smuzhiyun 			 * try to find an empty DAC
402*4882a593Smuzhiyun 			 */
403*4882a593Smuzhiyun 			if (from_nid ||
404*4882a593Smuzhiyun 			    get_wcaps_type(get_wcaps(codec, conn[i])) != AC_WID_AUD_OUT ||
405*4882a593Smuzhiyun 			    is_dac_already_used(codec, conn[i]))
406*4882a593Smuzhiyun 				continue;
407*4882a593Smuzhiyun 		}
408*4882a593Smuzhiyun 		/* anchor is not requested or already passed? */
409*4882a593Smuzhiyun 		if (anchor_nid <= 0)
410*4882a593Smuzhiyun 			goto found;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun 	if (depth >= MAX_NID_PATH_DEPTH)
413*4882a593Smuzhiyun 		return false;
414*4882a593Smuzhiyun 	for (i = 0; i < nums; i++) {
415*4882a593Smuzhiyun 		unsigned int type;
416*4882a593Smuzhiyun 		type = get_wcaps_type(get_wcaps(codec, conn[i]));
417*4882a593Smuzhiyun 		if (type == AC_WID_AUD_OUT || type == AC_WID_AUD_IN ||
418*4882a593Smuzhiyun 		    type == AC_WID_PIN)
419*4882a593Smuzhiyun 			continue;
420*4882a593Smuzhiyun 		if (__parse_nid_path(codec, from_nid, conn[i],
421*4882a593Smuzhiyun 				     anchor_nid, path, depth + 1))
422*4882a593Smuzhiyun 			goto found;
423*4882a593Smuzhiyun 	}
424*4882a593Smuzhiyun 	return false;
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun  found:
427*4882a593Smuzhiyun 	path->path[path->depth] = conn[i];
428*4882a593Smuzhiyun 	path->idx[path->depth + 1] = i;
429*4882a593Smuzhiyun 	if (nums > 1 && get_wcaps_type(get_wcaps(codec, to_nid)) != AC_WID_AUD_MIX)
430*4882a593Smuzhiyun 		path->multi[path->depth + 1] = 1;
431*4882a593Smuzhiyun 	path->depth++;
432*4882a593Smuzhiyun 	return true;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun /*
436*4882a593Smuzhiyun  * snd_hda_parse_nid_path - parse the widget path from the given nid to
437*4882a593Smuzhiyun  * the target nid
438*4882a593Smuzhiyun  * @codec: the HDA codec
439*4882a593Smuzhiyun  * @from_nid: the NID where the path start from
440*4882a593Smuzhiyun  * @to_nid: the NID where the path ends at
441*4882a593Smuzhiyun  * @anchor_nid: the anchor indication
442*4882a593Smuzhiyun  * @path: the path object to store the result
443*4882a593Smuzhiyun  *
444*4882a593Smuzhiyun  * Returns true if a matching path is found.
445*4882a593Smuzhiyun  *
446*4882a593Smuzhiyun  * The parsing behavior depends on parameters:
447*4882a593Smuzhiyun  * when @from_nid is 0, try to find an empty DAC;
448*4882a593Smuzhiyun  * when @anchor_nid is set to a positive value, only paths through the widget
449*4882a593Smuzhiyun  * with the given value are evaluated.
450*4882a593Smuzhiyun  * when @anchor_nid is set to a negative value, paths through the widget
451*4882a593Smuzhiyun  * with the negative of given value are excluded, only other paths are chosen.
452*4882a593Smuzhiyun  * when @anchor_nid is zero, no special handling about path selection.
453*4882a593Smuzhiyun  */
snd_hda_parse_nid_path(struct hda_codec * codec,hda_nid_t from_nid,hda_nid_t to_nid,int anchor_nid,struct nid_path * path)454*4882a593Smuzhiyun static bool snd_hda_parse_nid_path(struct hda_codec *codec, hda_nid_t from_nid,
455*4882a593Smuzhiyun 			    hda_nid_t to_nid, int anchor_nid,
456*4882a593Smuzhiyun 			    struct nid_path *path)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	if (__parse_nid_path(codec, from_nid, to_nid, anchor_nid, path, 1)) {
459*4882a593Smuzhiyun 		path->path[path->depth] = to_nid;
460*4882a593Smuzhiyun 		path->depth++;
461*4882a593Smuzhiyun 		return true;
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 	return false;
464*4882a593Smuzhiyun }
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun /**
467*4882a593Smuzhiyun  * snd_hda_add_new_path - parse the path between the given NIDs and
468*4882a593Smuzhiyun  * add to the path list
469*4882a593Smuzhiyun  * @codec: the HDA codec
470*4882a593Smuzhiyun  * @from_nid: the NID where the path start from
471*4882a593Smuzhiyun  * @to_nid: the NID where the path ends at
472*4882a593Smuzhiyun  * @anchor_nid: the anchor indication, see snd_hda_parse_nid_path()
473*4882a593Smuzhiyun  *
474*4882a593Smuzhiyun  * If no valid path is found, returns NULL.
475*4882a593Smuzhiyun  */
476*4882a593Smuzhiyun struct nid_path *
snd_hda_add_new_path(struct hda_codec * codec,hda_nid_t from_nid,hda_nid_t to_nid,int anchor_nid)477*4882a593Smuzhiyun snd_hda_add_new_path(struct hda_codec *codec, hda_nid_t from_nid,
478*4882a593Smuzhiyun 		     hda_nid_t to_nid, int anchor_nid)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
481*4882a593Smuzhiyun 	struct nid_path *path;
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun 	if (from_nid && to_nid && !is_reachable_path(codec, from_nid, to_nid))
484*4882a593Smuzhiyun 		return NULL;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun 	/* check whether the path has been already added */
487*4882a593Smuzhiyun 	path = get_nid_path(codec, from_nid, to_nid, anchor_nid);
488*4882a593Smuzhiyun 	if (path)
489*4882a593Smuzhiyun 		return path;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	path = snd_array_new(&spec->paths);
492*4882a593Smuzhiyun 	if (!path)
493*4882a593Smuzhiyun 		return NULL;
494*4882a593Smuzhiyun 	memset(path, 0, sizeof(*path));
495*4882a593Smuzhiyun 	if (snd_hda_parse_nid_path(codec, from_nid, to_nid, anchor_nid, path))
496*4882a593Smuzhiyun 		return path;
497*4882a593Smuzhiyun 	/* push back */
498*4882a593Smuzhiyun 	spec->paths.used--;
499*4882a593Smuzhiyun 	return NULL;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_add_new_path);
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun /* clear the given path as invalid so that it won't be picked up later */
invalidate_nid_path(struct hda_codec * codec,int idx)504*4882a593Smuzhiyun static void invalidate_nid_path(struct hda_codec *codec, int idx)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	struct nid_path *path = snd_hda_get_path_from_idx(codec, idx);
507*4882a593Smuzhiyun 	if (!path)
508*4882a593Smuzhiyun 		return;
509*4882a593Smuzhiyun 	memset(path, 0, sizeof(*path));
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun /* return a DAC if paired to the given pin by codec driver */
get_preferred_dac(struct hda_codec * codec,hda_nid_t pin)513*4882a593Smuzhiyun static hda_nid_t get_preferred_dac(struct hda_codec *codec, hda_nid_t pin)
514*4882a593Smuzhiyun {
515*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
516*4882a593Smuzhiyun 	const hda_nid_t *list = spec->preferred_dacs;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	if (!list)
519*4882a593Smuzhiyun 		return 0;
520*4882a593Smuzhiyun 	for (; *list; list += 2)
521*4882a593Smuzhiyun 		if (*list == pin)
522*4882a593Smuzhiyun 			return list[1];
523*4882a593Smuzhiyun 	return 0;
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun /* look for an empty DAC slot */
look_for_dac(struct hda_codec * codec,hda_nid_t pin,bool is_digital)527*4882a593Smuzhiyun static hda_nid_t look_for_dac(struct hda_codec *codec, hda_nid_t pin,
528*4882a593Smuzhiyun 			      bool is_digital)
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
531*4882a593Smuzhiyun 	bool cap_digital;
532*4882a593Smuzhiyun 	int i;
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	for (i = 0; i < spec->num_all_dacs; i++) {
535*4882a593Smuzhiyun 		hda_nid_t nid = spec->all_dacs[i];
536*4882a593Smuzhiyun 		if (!nid || is_dac_already_used(codec, nid))
537*4882a593Smuzhiyun 			continue;
538*4882a593Smuzhiyun 		cap_digital = !!(get_wcaps(codec, nid) & AC_WCAP_DIGITAL);
539*4882a593Smuzhiyun 		if (is_digital != cap_digital)
540*4882a593Smuzhiyun 			continue;
541*4882a593Smuzhiyun 		if (is_reachable_path(codec, nid, pin))
542*4882a593Smuzhiyun 			return nid;
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun 	return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun /* replace the channels in the composed amp value with the given number */
amp_val_replace_channels(unsigned int val,unsigned int chs)548*4882a593Smuzhiyun static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	val &= ~(0x3U << 16);
551*4882a593Smuzhiyun 	val |= chs << 16;
552*4882a593Smuzhiyun 	return val;
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun 
same_amp_caps(struct hda_codec * codec,hda_nid_t nid1,hda_nid_t nid2,int dir)555*4882a593Smuzhiyun static bool same_amp_caps(struct hda_codec *codec, hda_nid_t nid1,
556*4882a593Smuzhiyun 			  hda_nid_t nid2, int dir)
557*4882a593Smuzhiyun {
558*4882a593Smuzhiyun 	if (!(get_wcaps(codec, nid1) & (1 << (dir + 1))))
559*4882a593Smuzhiyun 		return !(get_wcaps(codec, nid2) & (1 << (dir + 1)));
560*4882a593Smuzhiyun 	return (query_amp_caps(codec, nid1, dir) ==
561*4882a593Smuzhiyun 		query_amp_caps(codec, nid2, dir));
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun /* look for a widget suitable for assigning a mute switch in the path */
look_for_out_mute_nid(struct hda_codec * codec,struct nid_path * path)565*4882a593Smuzhiyun static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec,
566*4882a593Smuzhiyun 				       struct nid_path *path)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun 	int i;
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	for (i = path->depth - 1; i >= 0; i--) {
571*4882a593Smuzhiyun 		if (nid_has_mute(codec, path->path[i], HDA_OUTPUT))
572*4882a593Smuzhiyun 			return path->path[i];
573*4882a593Smuzhiyun 		if (i != path->depth - 1 && i != 0 &&
574*4882a593Smuzhiyun 		    nid_has_mute(codec, path->path[i], HDA_INPUT))
575*4882a593Smuzhiyun 			return path->path[i];
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun 	return 0;
578*4882a593Smuzhiyun }
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun /* look for a widget suitable for assigning a volume ctl in the path */
look_for_out_vol_nid(struct hda_codec * codec,struct nid_path * path)581*4882a593Smuzhiyun static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec,
582*4882a593Smuzhiyun 				      struct nid_path *path)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
585*4882a593Smuzhiyun 	int i;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun 	for (i = path->depth - 1; i >= 0; i--) {
588*4882a593Smuzhiyun 		hda_nid_t nid = path->path[i];
589*4882a593Smuzhiyun 		if ((spec->out_vol_mask >> nid) & 1)
590*4882a593Smuzhiyun 			continue;
591*4882a593Smuzhiyun 		if (nid_has_volume(codec, nid, HDA_OUTPUT))
592*4882a593Smuzhiyun 			return nid;
593*4882a593Smuzhiyun 	}
594*4882a593Smuzhiyun 	return 0;
595*4882a593Smuzhiyun }
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun /*
598*4882a593Smuzhiyun  * path activation / deactivation
599*4882a593Smuzhiyun  */
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun /* can have the amp-in capability? */
has_amp_in(struct hda_codec * codec,struct nid_path * path,int idx)602*4882a593Smuzhiyun static bool has_amp_in(struct hda_codec *codec, struct nid_path *path, int idx)
603*4882a593Smuzhiyun {
604*4882a593Smuzhiyun 	hda_nid_t nid = path->path[idx];
605*4882a593Smuzhiyun 	unsigned int caps = get_wcaps(codec, nid);
606*4882a593Smuzhiyun 	unsigned int type = get_wcaps_type(caps);
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	if (!(caps & AC_WCAP_IN_AMP))
609*4882a593Smuzhiyun 		return false;
610*4882a593Smuzhiyun 	if (type == AC_WID_PIN && idx > 0) /* only for input pins */
611*4882a593Smuzhiyun 		return false;
612*4882a593Smuzhiyun 	return true;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun /* can have the amp-out capability? */
has_amp_out(struct hda_codec * codec,struct nid_path * path,int idx)616*4882a593Smuzhiyun static bool has_amp_out(struct hda_codec *codec, struct nid_path *path, int idx)
617*4882a593Smuzhiyun {
618*4882a593Smuzhiyun 	hda_nid_t nid = path->path[idx];
619*4882a593Smuzhiyun 	unsigned int caps = get_wcaps(codec, nid);
620*4882a593Smuzhiyun 	unsigned int type = get_wcaps_type(caps);
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if (!(caps & AC_WCAP_OUT_AMP))
623*4882a593Smuzhiyun 		return false;
624*4882a593Smuzhiyun 	if (type == AC_WID_PIN && !idx) /* only for output pins */
625*4882a593Smuzhiyun 		return false;
626*4882a593Smuzhiyun 	return true;
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun /* check whether the given (nid,dir,idx) is active */
is_active_nid(struct hda_codec * codec,hda_nid_t nid,unsigned int dir,unsigned int idx)630*4882a593Smuzhiyun static bool is_active_nid(struct hda_codec *codec, hda_nid_t nid,
631*4882a593Smuzhiyun 			  unsigned int dir, unsigned int idx)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
634*4882a593Smuzhiyun 	int type = get_wcaps_type(get_wcaps(codec, nid));
635*4882a593Smuzhiyun 	const struct nid_path *path;
636*4882a593Smuzhiyun 	int i, n;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	if (nid == codec->core.afg)
639*4882a593Smuzhiyun 		return true;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	snd_array_for_each(&spec->paths, n, path) {
642*4882a593Smuzhiyun 		if (!path->active)
643*4882a593Smuzhiyun 			continue;
644*4882a593Smuzhiyun 		if (codec->power_save_node) {
645*4882a593Smuzhiyun 			if (!path->stream_enabled)
646*4882a593Smuzhiyun 				continue;
647*4882a593Smuzhiyun 			/* ignore unplugged paths except for DAC/ADC */
648*4882a593Smuzhiyun 			if (!(path->pin_enabled || path->pin_fixed) &&
649*4882a593Smuzhiyun 			    type != AC_WID_AUD_OUT && type != AC_WID_AUD_IN)
650*4882a593Smuzhiyun 				continue;
651*4882a593Smuzhiyun 		}
652*4882a593Smuzhiyun 		for (i = 0; i < path->depth; i++) {
653*4882a593Smuzhiyun 			if (path->path[i] == nid) {
654*4882a593Smuzhiyun 				if (dir == HDA_OUTPUT || idx == -1 ||
655*4882a593Smuzhiyun 				    path->idx[i] == idx)
656*4882a593Smuzhiyun 					return true;
657*4882a593Smuzhiyun 				break;
658*4882a593Smuzhiyun 			}
659*4882a593Smuzhiyun 		}
660*4882a593Smuzhiyun 	}
661*4882a593Smuzhiyun 	return false;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun /* check whether the NID is referred by any active paths */
665*4882a593Smuzhiyun #define is_active_nid_for_any(codec, nid) \
666*4882a593Smuzhiyun 	is_active_nid(codec, nid, HDA_OUTPUT, -1)
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun /* get the default amp value for the target state */
get_amp_val_to_activate(struct hda_codec * codec,hda_nid_t nid,int dir,unsigned int caps,bool enable)669*4882a593Smuzhiyun static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
670*4882a593Smuzhiyun 				   int dir, unsigned int caps, bool enable)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun 	unsigned int val = 0;
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	if (caps & AC_AMPCAP_NUM_STEPS) {
675*4882a593Smuzhiyun 		/* set to 0dB */
676*4882a593Smuzhiyun 		if (enable)
677*4882a593Smuzhiyun 			val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
678*4882a593Smuzhiyun 	}
679*4882a593Smuzhiyun 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
680*4882a593Smuzhiyun 		if (!enable)
681*4882a593Smuzhiyun 			val |= HDA_AMP_MUTE;
682*4882a593Smuzhiyun 	}
683*4882a593Smuzhiyun 	return val;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun /* is this a stereo widget or a stereo-to-mono mix? */
is_stereo_amps(struct hda_codec * codec,hda_nid_t nid,int dir)687*4882a593Smuzhiyun static bool is_stereo_amps(struct hda_codec *codec, hda_nid_t nid, int dir)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun 	unsigned int wcaps = get_wcaps(codec, nid);
690*4882a593Smuzhiyun 	hda_nid_t conn;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	if (wcaps & AC_WCAP_STEREO)
693*4882a593Smuzhiyun 		return true;
694*4882a593Smuzhiyun 	if (dir != HDA_INPUT || get_wcaps_type(wcaps) != AC_WID_AUD_MIX)
695*4882a593Smuzhiyun 		return false;
696*4882a593Smuzhiyun 	if (snd_hda_get_num_conns(codec, nid) != 1)
697*4882a593Smuzhiyun 		return false;
698*4882a593Smuzhiyun 	if (snd_hda_get_connections(codec, nid, &conn, 1) < 0)
699*4882a593Smuzhiyun 		return false;
700*4882a593Smuzhiyun 	return !!(get_wcaps(codec, conn) & AC_WCAP_STEREO);
701*4882a593Smuzhiyun }
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun /* initialize the amp value (only at the first time) */
init_amp(struct hda_codec * codec,hda_nid_t nid,int dir,int idx)704*4882a593Smuzhiyun static void init_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun 	unsigned int caps = query_amp_caps(codec, nid, dir);
707*4882a593Smuzhiyun 	int val = get_amp_val_to_activate(codec, nid, dir, caps, false);
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun 	if (is_stereo_amps(codec, nid, dir))
710*4882a593Smuzhiyun 		snd_hda_codec_amp_init_stereo(codec, nid, dir, idx, 0xff, val);
711*4882a593Smuzhiyun 	else
712*4882a593Smuzhiyun 		snd_hda_codec_amp_init(codec, nid, 0, dir, idx, 0xff, val);
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun /* update the amp, doing in stereo or mono depending on NID */
update_amp(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,unsigned int mask,unsigned int val)716*4882a593Smuzhiyun static int update_amp(struct hda_codec *codec, hda_nid_t nid, int dir, int idx,
717*4882a593Smuzhiyun 		      unsigned int mask, unsigned int val)
718*4882a593Smuzhiyun {
719*4882a593Smuzhiyun 	if (is_stereo_amps(codec, nid, dir))
720*4882a593Smuzhiyun 		return snd_hda_codec_amp_stereo(codec, nid, dir, idx,
721*4882a593Smuzhiyun 						mask, val);
722*4882a593Smuzhiyun 	else
723*4882a593Smuzhiyun 		return snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
724*4882a593Smuzhiyun 						mask, val);
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun /* calculate amp value mask we can modify;
728*4882a593Smuzhiyun  * if the given amp is controlled by mixers, don't touch it
729*4882a593Smuzhiyun  */
get_amp_mask_to_modify(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,unsigned int caps)730*4882a593Smuzhiyun static unsigned int get_amp_mask_to_modify(struct hda_codec *codec,
731*4882a593Smuzhiyun 					   hda_nid_t nid, int dir, int idx,
732*4882a593Smuzhiyun 					   unsigned int caps)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	unsigned int mask = 0xff;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	if (caps & (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) {
737*4882a593Smuzhiyun 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_MUTE_CTL))
738*4882a593Smuzhiyun 			mask &= ~0x80;
739*4882a593Smuzhiyun 	}
740*4882a593Smuzhiyun 	if (caps & AC_AMPCAP_NUM_STEPS) {
741*4882a593Smuzhiyun 		if (is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
742*4882a593Smuzhiyun 		    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
743*4882a593Smuzhiyun 			mask &= ~0x7f;
744*4882a593Smuzhiyun 	}
745*4882a593Smuzhiyun 	return mask;
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun 
activate_amp(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,int idx_to_check,bool enable)748*4882a593Smuzhiyun static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
749*4882a593Smuzhiyun 			 int idx, int idx_to_check, bool enable)
750*4882a593Smuzhiyun {
751*4882a593Smuzhiyun 	unsigned int caps;
752*4882a593Smuzhiyun 	unsigned int mask, val;
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	caps = query_amp_caps(codec, nid, dir);
755*4882a593Smuzhiyun 	val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
756*4882a593Smuzhiyun 	mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
757*4882a593Smuzhiyun 	if (!mask)
758*4882a593Smuzhiyun 		return;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun 	val &= mask;
761*4882a593Smuzhiyun 	update_amp(codec, nid, dir, idx, mask, val);
762*4882a593Smuzhiyun }
763*4882a593Smuzhiyun 
check_and_activate_amp(struct hda_codec * codec,hda_nid_t nid,int dir,int idx,int idx_to_check,bool enable)764*4882a593Smuzhiyun static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
765*4882a593Smuzhiyun 				   int dir, int idx, int idx_to_check,
766*4882a593Smuzhiyun 				   bool enable)
767*4882a593Smuzhiyun {
768*4882a593Smuzhiyun 	/* check whether the given amp is still used by others */
769*4882a593Smuzhiyun 	if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
770*4882a593Smuzhiyun 		return;
771*4882a593Smuzhiyun 	activate_amp(codec, nid, dir, idx, idx_to_check, enable);
772*4882a593Smuzhiyun }
773*4882a593Smuzhiyun 
activate_amp_out(struct hda_codec * codec,struct nid_path * path,int i,bool enable)774*4882a593Smuzhiyun static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
775*4882a593Smuzhiyun 			     int i, bool enable)
776*4882a593Smuzhiyun {
777*4882a593Smuzhiyun 	hda_nid_t nid = path->path[i];
778*4882a593Smuzhiyun 	init_amp(codec, nid, HDA_OUTPUT, 0);
779*4882a593Smuzhiyun 	check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun 
activate_amp_in(struct hda_codec * codec,struct nid_path * path,int i,bool enable,bool add_aamix)782*4882a593Smuzhiyun static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
783*4882a593Smuzhiyun 			    int i, bool enable, bool add_aamix)
784*4882a593Smuzhiyun {
785*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
786*4882a593Smuzhiyun 	const hda_nid_t *conn;
787*4882a593Smuzhiyun 	int n, nums, idx;
788*4882a593Smuzhiyun 	int type;
789*4882a593Smuzhiyun 	hda_nid_t nid = path->path[i];
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun 	nums = snd_hda_get_conn_list(codec, nid, &conn);
792*4882a593Smuzhiyun 	if (nums < 0)
793*4882a593Smuzhiyun 		return;
794*4882a593Smuzhiyun 	type = get_wcaps_type(get_wcaps(codec, nid));
795*4882a593Smuzhiyun 	if (type == AC_WID_PIN ||
796*4882a593Smuzhiyun 	    (type == AC_WID_AUD_IN && codec->single_adc_amp)) {
797*4882a593Smuzhiyun 		nums = 1;
798*4882a593Smuzhiyun 		idx = 0;
799*4882a593Smuzhiyun 	} else
800*4882a593Smuzhiyun 		idx = path->idx[i];
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	for (n = 0; n < nums; n++)
803*4882a593Smuzhiyun 		init_amp(codec, nid, HDA_INPUT, n);
804*4882a593Smuzhiyun 
805*4882a593Smuzhiyun 	/* here is a little bit tricky in comparison with activate_amp_out();
806*4882a593Smuzhiyun 	 * when aa-mixer is available, we need to enable the path as well
807*4882a593Smuzhiyun 	 */
808*4882a593Smuzhiyun 	for (n = 0; n < nums; n++) {
809*4882a593Smuzhiyun 		if (n != idx) {
810*4882a593Smuzhiyun 			if (conn[n] != spec->mixer_merge_nid)
811*4882a593Smuzhiyun 				continue;
812*4882a593Smuzhiyun 			/* when aamix is disabled, force to off */
813*4882a593Smuzhiyun 			if (!add_aamix) {
814*4882a593Smuzhiyun 				activate_amp(codec, nid, HDA_INPUT, n, n, false);
815*4882a593Smuzhiyun 				continue;
816*4882a593Smuzhiyun 			}
817*4882a593Smuzhiyun 		}
818*4882a593Smuzhiyun 		check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
819*4882a593Smuzhiyun 	}
820*4882a593Smuzhiyun }
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun /* sync power of each widget in the given path */
path_power_update(struct hda_codec * codec,struct nid_path * path,bool allow_powerdown)823*4882a593Smuzhiyun static hda_nid_t path_power_update(struct hda_codec *codec,
824*4882a593Smuzhiyun 				   struct nid_path *path,
825*4882a593Smuzhiyun 				   bool allow_powerdown)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun 	hda_nid_t nid, changed = 0;
828*4882a593Smuzhiyun 	int i, state, power;
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	for (i = 0; i < path->depth; i++) {
831*4882a593Smuzhiyun 		nid = path->path[i];
832*4882a593Smuzhiyun 		if (!(get_wcaps(codec, nid) & AC_WCAP_POWER))
833*4882a593Smuzhiyun 			continue;
834*4882a593Smuzhiyun 		if (nid == codec->core.afg)
835*4882a593Smuzhiyun 			continue;
836*4882a593Smuzhiyun 		if (!allow_powerdown || is_active_nid_for_any(codec, nid))
837*4882a593Smuzhiyun 			state = AC_PWRST_D0;
838*4882a593Smuzhiyun 		else
839*4882a593Smuzhiyun 			state = AC_PWRST_D3;
840*4882a593Smuzhiyun 		power = snd_hda_codec_read(codec, nid, 0,
841*4882a593Smuzhiyun 					   AC_VERB_GET_POWER_STATE, 0);
842*4882a593Smuzhiyun 		if (power != (state | (state << 4))) {
843*4882a593Smuzhiyun 			snd_hda_codec_write(codec, nid, 0,
844*4882a593Smuzhiyun 					    AC_VERB_SET_POWER_STATE, state);
845*4882a593Smuzhiyun 			changed = nid;
846*4882a593Smuzhiyun 			/* all known codecs seem to be capable to handl
847*4882a593Smuzhiyun 			 * widgets state even in D3, so far.
848*4882a593Smuzhiyun 			 * if any new codecs need to restore the widget
849*4882a593Smuzhiyun 			 * states after D0 transition, call the function
850*4882a593Smuzhiyun 			 * below.
851*4882a593Smuzhiyun 			 */
852*4882a593Smuzhiyun #if 0 /* disabled */
853*4882a593Smuzhiyun 			if (state == AC_PWRST_D0)
854*4882a593Smuzhiyun 				snd_hdac_regmap_sync_node(&codec->core, nid);
855*4882a593Smuzhiyun #endif
856*4882a593Smuzhiyun 		}
857*4882a593Smuzhiyun 	}
858*4882a593Smuzhiyun 	return changed;
859*4882a593Smuzhiyun }
860*4882a593Smuzhiyun 
861*4882a593Smuzhiyun /* do sync with the last power state change */
sync_power_state_change(struct hda_codec * codec,hda_nid_t nid)862*4882a593Smuzhiyun static void sync_power_state_change(struct hda_codec *codec, hda_nid_t nid)
863*4882a593Smuzhiyun {
864*4882a593Smuzhiyun 	if (nid) {
865*4882a593Smuzhiyun 		msleep(10);
866*4882a593Smuzhiyun 		snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_POWER_STATE, 0);
867*4882a593Smuzhiyun 	}
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun /**
871*4882a593Smuzhiyun  * snd_hda_activate_path - activate or deactivate the given path
872*4882a593Smuzhiyun  * @codec: the HDA codec
873*4882a593Smuzhiyun  * @path: the path to activate/deactivate
874*4882a593Smuzhiyun  * @enable: flag to activate or not
875*4882a593Smuzhiyun  * @add_aamix: enable the input from aamix NID
876*4882a593Smuzhiyun  *
877*4882a593Smuzhiyun  * If @add_aamix is set, enable the input from aa-mix NID as well (if any).
878*4882a593Smuzhiyun  */
snd_hda_activate_path(struct hda_codec * codec,struct nid_path * path,bool enable,bool add_aamix)879*4882a593Smuzhiyun void snd_hda_activate_path(struct hda_codec *codec, struct nid_path *path,
880*4882a593Smuzhiyun 			   bool enable, bool add_aamix)
881*4882a593Smuzhiyun {
882*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
883*4882a593Smuzhiyun 	int i;
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun 	path->active = enable;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	/* make sure the widget is powered up */
888*4882a593Smuzhiyun 	if (enable && (spec->power_down_unused || codec->power_save_node))
889*4882a593Smuzhiyun 		path_power_update(codec, path, codec->power_save_node);
890*4882a593Smuzhiyun 
891*4882a593Smuzhiyun 	for (i = path->depth - 1; i >= 0; i--) {
892*4882a593Smuzhiyun 		hda_nid_t nid = path->path[i];
893*4882a593Smuzhiyun 
894*4882a593Smuzhiyun 		if (enable && path->multi[i])
895*4882a593Smuzhiyun 			snd_hda_codec_write_cache(codec, nid, 0,
896*4882a593Smuzhiyun 					    AC_VERB_SET_CONNECT_SEL,
897*4882a593Smuzhiyun 					    path->idx[i]);
898*4882a593Smuzhiyun 		if (has_amp_in(codec, path, i))
899*4882a593Smuzhiyun 			activate_amp_in(codec, path, i, enable, add_aamix);
900*4882a593Smuzhiyun 		if (has_amp_out(codec, path, i))
901*4882a593Smuzhiyun 			activate_amp_out(codec, path, i, enable);
902*4882a593Smuzhiyun 	}
903*4882a593Smuzhiyun }
904*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_activate_path);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun /* if the given path is inactive, put widgets into D3 (only if suitable) */
path_power_down_sync(struct hda_codec * codec,struct nid_path * path)907*4882a593Smuzhiyun static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
908*4882a593Smuzhiyun {
909*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun 	if (!(spec->power_down_unused || codec->power_save_node) || path->active)
912*4882a593Smuzhiyun 		return;
913*4882a593Smuzhiyun 	sync_power_state_change(codec, path_power_update(codec, path, true));
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun /* turn on/off EAPD on the given pin */
set_pin_eapd(struct hda_codec * codec,hda_nid_t pin,bool enable)917*4882a593Smuzhiyun static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
920*4882a593Smuzhiyun 	if (spec->own_eapd_ctl ||
921*4882a593Smuzhiyun 	    !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD))
922*4882a593Smuzhiyun 		return;
923*4882a593Smuzhiyun 	if (spec->keep_eapd_on && !enable)
924*4882a593Smuzhiyun 		return;
925*4882a593Smuzhiyun 	if (codec->inv_eapd)
926*4882a593Smuzhiyun 		enable = !enable;
927*4882a593Smuzhiyun 	snd_hda_codec_write_cache(codec, pin, 0,
928*4882a593Smuzhiyun 				   AC_VERB_SET_EAPD_BTLENABLE,
929*4882a593Smuzhiyun 				   enable ? 0x02 : 0x00);
930*4882a593Smuzhiyun }
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun /* re-initialize the path specified by the given path index */
resume_path_from_idx(struct hda_codec * codec,int path_idx)933*4882a593Smuzhiyun static void resume_path_from_idx(struct hda_codec *codec, int path_idx)
934*4882a593Smuzhiyun {
935*4882a593Smuzhiyun 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
936*4882a593Smuzhiyun 	if (path)
937*4882a593Smuzhiyun 		snd_hda_activate_path(codec, path, path->active, false);
938*4882a593Smuzhiyun }
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun /*
942*4882a593Smuzhiyun  * Helper functions for creating mixer ctl elements
943*4882a593Smuzhiyun  */
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
946*4882a593Smuzhiyun 				  struct snd_ctl_elem_value *ucontrol);
947*4882a593Smuzhiyun static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
948*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol);
949*4882a593Smuzhiyun static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
950*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol);
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun enum {
953*4882a593Smuzhiyun 	HDA_CTL_WIDGET_VOL,
954*4882a593Smuzhiyun 	HDA_CTL_WIDGET_MUTE,
955*4882a593Smuzhiyun 	HDA_CTL_BIND_MUTE,
956*4882a593Smuzhiyun };
957*4882a593Smuzhiyun static const struct snd_kcontrol_new control_templates[] = {
958*4882a593Smuzhiyun 	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
959*4882a593Smuzhiyun 	/* only the put callback is replaced for handling the special mute */
960*4882a593Smuzhiyun 	{
961*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
962*4882a593Smuzhiyun 		.subdevice = HDA_SUBDEV_AMP_FLAG,
963*4882a593Smuzhiyun 		.info = snd_hda_mixer_amp_switch_info,
964*4882a593Smuzhiyun 		.get = snd_hda_mixer_amp_switch_get,
965*4882a593Smuzhiyun 		.put = hda_gen_mixer_mute_put, /* replaced */
966*4882a593Smuzhiyun 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
967*4882a593Smuzhiyun 	},
968*4882a593Smuzhiyun 	{
969*4882a593Smuzhiyun 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
970*4882a593Smuzhiyun 		.info = snd_hda_mixer_amp_switch_info,
971*4882a593Smuzhiyun 		.get = hda_gen_bind_mute_get,
972*4882a593Smuzhiyun 		.put = hda_gen_bind_mute_put, /* replaced */
973*4882a593Smuzhiyun 		.private_value = HDA_COMPOSE_AMP_VAL(0, 3, 0, 0),
974*4882a593Smuzhiyun 	},
975*4882a593Smuzhiyun };
976*4882a593Smuzhiyun 
977*4882a593Smuzhiyun /* add dynamic controls from template */
978*4882a593Smuzhiyun static struct snd_kcontrol_new *
add_control(struct hda_gen_spec * spec,int type,const char * name,int cidx,unsigned long val)979*4882a593Smuzhiyun add_control(struct hda_gen_spec *spec, int type, const char *name,
980*4882a593Smuzhiyun 		       int cidx, unsigned long val)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew;
983*4882a593Smuzhiyun 
984*4882a593Smuzhiyun 	knew = snd_hda_gen_add_kctl(spec, name, &control_templates[type]);
985*4882a593Smuzhiyun 	if (!knew)
986*4882a593Smuzhiyun 		return NULL;
987*4882a593Smuzhiyun 	knew->index = cidx;
988*4882a593Smuzhiyun 	if (get_amp_nid_(val))
989*4882a593Smuzhiyun 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
990*4882a593Smuzhiyun 	knew->private_value = val;
991*4882a593Smuzhiyun 	return knew;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
add_control_with_pfx(struct hda_gen_spec * spec,int type,const char * pfx,const char * dir,const char * sfx,int cidx,unsigned long val)994*4882a593Smuzhiyun static int add_control_with_pfx(struct hda_gen_spec *spec, int type,
995*4882a593Smuzhiyun 				const char *pfx, const char *dir,
996*4882a593Smuzhiyun 				const char *sfx, int cidx, unsigned long val)
997*4882a593Smuzhiyun {
998*4882a593Smuzhiyun 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
999*4882a593Smuzhiyun 	snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx);
1000*4882a593Smuzhiyun 	if (!add_control(spec, type, name, cidx, val))
1001*4882a593Smuzhiyun 		return -ENOMEM;
1002*4882a593Smuzhiyun 	return 0;
1003*4882a593Smuzhiyun }
1004*4882a593Smuzhiyun 
1005*4882a593Smuzhiyun #define add_pb_vol_ctrl(spec, type, pfx, val)			\
1006*4882a593Smuzhiyun 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val)
1007*4882a593Smuzhiyun #define add_pb_sw_ctrl(spec, type, pfx, val)			\
1008*4882a593Smuzhiyun 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val)
1009*4882a593Smuzhiyun #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val)			\
1010*4882a593Smuzhiyun 	add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val)
1011*4882a593Smuzhiyun #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val)			\
1012*4882a593Smuzhiyun 	add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
1013*4882a593Smuzhiyun 
add_vol_ctl(struct hda_codec * codec,const char * pfx,int cidx,unsigned int chs,struct nid_path * path)1014*4882a593Smuzhiyun static int add_vol_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1015*4882a593Smuzhiyun 		       unsigned int chs, struct nid_path *path)
1016*4882a593Smuzhiyun {
1017*4882a593Smuzhiyun 	unsigned int val;
1018*4882a593Smuzhiyun 	if (!path)
1019*4882a593Smuzhiyun 		return 0;
1020*4882a593Smuzhiyun 	val = path->ctls[NID_PATH_VOL_CTL];
1021*4882a593Smuzhiyun 	if (!val)
1022*4882a593Smuzhiyun 		return 0;
1023*4882a593Smuzhiyun 	val = amp_val_replace_channels(val, chs);
1024*4882a593Smuzhiyun 	return __add_pb_vol_ctrl(codec->spec, HDA_CTL_WIDGET_VOL, pfx, cidx, val);
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun /* return the channel bits suitable for the given path->ctls[] */
get_default_ch_nums(struct hda_codec * codec,struct nid_path * path,int type)1028*4882a593Smuzhiyun static int get_default_ch_nums(struct hda_codec *codec, struct nid_path *path,
1029*4882a593Smuzhiyun 			       int type)
1030*4882a593Smuzhiyun {
1031*4882a593Smuzhiyun 	int chs = 1; /* mono (left only) */
1032*4882a593Smuzhiyun 	if (path) {
1033*4882a593Smuzhiyun 		hda_nid_t nid = get_amp_nid_(path->ctls[type]);
1034*4882a593Smuzhiyun 		if (nid && (get_wcaps(codec, nid) & AC_WCAP_STEREO))
1035*4882a593Smuzhiyun 			chs = 3; /* stereo */
1036*4882a593Smuzhiyun 	}
1037*4882a593Smuzhiyun 	return chs;
1038*4882a593Smuzhiyun }
1039*4882a593Smuzhiyun 
add_stereo_vol(struct hda_codec * codec,const char * pfx,int cidx,struct nid_path * path)1040*4882a593Smuzhiyun static int add_stereo_vol(struct hda_codec *codec, const char *pfx, int cidx,
1041*4882a593Smuzhiyun 			  struct nid_path *path)
1042*4882a593Smuzhiyun {
1043*4882a593Smuzhiyun 	int chs = get_default_ch_nums(codec, path, NID_PATH_VOL_CTL);
1044*4882a593Smuzhiyun 	return add_vol_ctl(codec, pfx, cidx, chs, path);
1045*4882a593Smuzhiyun }
1046*4882a593Smuzhiyun 
1047*4882a593Smuzhiyun /* create a mute-switch for the given mixer widget;
1048*4882a593Smuzhiyun  * if it has multiple sources (e.g. DAC and loopback), create a bind-mute
1049*4882a593Smuzhiyun  */
add_sw_ctl(struct hda_codec * codec,const char * pfx,int cidx,unsigned int chs,struct nid_path * path)1050*4882a593Smuzhiyun static int add_sw_ctl(struct hda_codec *codec, const char *pfx, int cidx,
1051*4882a593Smuzhiyun 		      unsigned int chs, struct nid_path *path)
1052*4882a593Smuzhiyun {
1053*4882a593Smuzhiyun 	unsigned int val;
1054*4882a593Smuzhiyun 	int type = HDA_CTL_WIDGET_MUTE;
1055*4882a593Smuzhiyun 
1056*4882a593Smuzhiyun 	if (!path)
1057*4882a593Smuzhiyun 		return 0;
1058*4882a593Smuzhiyun 	val = path->ctls[NID_PATH_MUTE_CTL];
1059*4882a593Smuzhiyun 	if (!val)
1060*4882a593Smuzhiyun 		return 0;
1061*4882a593Smuzhiyun 	val = amp_val_replace_channels(val, chs);
1062*4882a593Smuzhiyun 	if (get_amp_direction_(val) == HDA_INPUT) {
1063*4882a593Smuzhiyun 		hda_nid_t nid = get_amp_nid_(val);
1064*4882a593Smuzhiyun 		int nums = snd_hda_get_num_conns(codec, nid);
1065*4882a593Smuzhiyun 		if (nums > 1) {
1066*4882a593Smuzhiyun 			type = HDA_CTL_BIND_MUTE;
1067*4882a593Smuzhiyun 			val |= nums << 19;
1068*4882a593Smuzhiyun 		}
1069*4882a593Smuzhiyun 	}
1070*4882a593Smuzhiyun 	return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun 
add_stereo_sw(struct hda_codec * codec,const char * pfx,int cidx,struct nid_path * path)1073*4882a593Smuzhiyun static int add_stereo_sw(struct hda_codec *codec, const char *pfx,
1074*4882a593Smuzhiyun 				  int cidx, struct nid_path *path)
1075*4882a593Smuzhiyun {
1076*4882a593Smuzhiyun 	int chs = get_default_ch_nums(codec, path, NID_PATH_MUTE_CTL);
1077*4882a593Smuzhiyun 	return add_sw_ctl(codec, pfx, cidx, chs, path);
1078*4882a593Smuzhiyun }
1079*4882a593Smuzhiyun 
1080*4882a593Smuzhiyun /* playback mute control with the software mute bit check */
sync_auto_mute_bits(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1081*4882a593Smuzhiyun static void sync_auto_mute_bits(struct snd_kcontrol *kcontrol,
1082*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
1083*4882a593Smuzhiyun {
1084*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1085*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1086*4882a593Smuzhiyun 
1087*4882a593Smuzhiyun 	if (spec->auto_mute_via_amp) {
1088*4882a593Smuzhiyun 		hda_nid_t nid = get_amp_nid(kcontrol);
1089*4882a593Smuzhiyun 		bool enabled = !((spec->mute_bits >> nid) & 1);
1090*4882a593Smuzhiyun 		ucontrol->value.integer.value[0] &= enabled;
1091*4882a593Smuzhiyun 		ucontrol->value.integer.value[1] &= enabled;
1092*4882a593Smuzhiyun 	}
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun 
hda_gen_mixer_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1095*4882a593Smuzhiyun static int hda_gen_mixer_mute_put(struct snd_kcontrol *kcontrol,
1096*4882a593Smuzhiyun 				  struct snd_ctl_elem_value *ucontrol)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun 	sync_auto_mute_bits(kcontrol, ucontrol);
1099*4882a593Smuzhiyun 	return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1100*4882a593Smuzhiyun }
1101*4882a593Smuzhiyun 
1102*4882a593Smuzhiyun /*
1103*4882a593Smuzhiyun  * Bound mute controls
1104*4882a593Smuzhiyun  */
1105*4882a593Smuzhiyun #define AMP_VAL_IDX_SHIFT	19
1106*4882a593Smuzhiyun #define AMP_VAL_IDX_MASK	(0x0f<<19)
1107*4882a593Smuzhiyun 
hda_gen_bind_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1108*4882a593Smuzhiyun static int hda_gen_bind_mute_get(struct snd_kcontrol *kcontrol,
1109*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
1110*4882a593Smuzhiyun {
1111*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1112*4882a593Smuzhiyun 	unsigned long pval;
1113*4882a593Smuzhiyun 	int err;
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun 	mutex_lock(&codec->control_mutex);
1116*4882a593Smuzhiyun 	pval = kcontrol->private_value;
1117*4882a593Smuzhiyun 	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
1118*4882a593Smuzhiyun 	err = snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
1119*4882a593Smuzhiyun 	kcontrol->private_value = pval;
1120*4882a593Smuzhiyun 	mutex_unlock(&codec->control_mutex);
1121*4882a593Smuzhiyun 	return err;
1122*4882a593Smuzhiyun }
1123*4882a593Smuzhiyun 
hda_gen_bind_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1124*4882a593Smuzhiyun static int hda_gen_bind_mute_put(struct snd_kcontrol *kcontrol,
1125*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
1128*4882a593Smuzhiyun 	unsigned long pval;
1129*4882a593Smuzhiyun 	int i, indices, err = 0, change = 0;
1130*4882a593Smuzhiyun 
1131*4882a593Smuzhiyun 	sync_auto_mute_bits(kcontrol, ucontrol);
1132*4882a593Smuzhiyun 
1133*4882a593Smuzhiyun 	mutex_lock(&codec->control_mutex);
1134*4882a593Smuzhiyun 	pval = kcontrol->private_value;
1135*4882a593Smuzhiyun 	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
1136*4882a593Smuzhiyun 	for (i = 0; i < indices; i++) {
1137*4882a593Smuzhiyun 		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) |
1138*4882a593Smuzhiyun 			(i << AMP_VAL_IDX_SHIFT);
1139*4882a593Smuzhiyun 		err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
1140*4882a593Smuzhiyun 		if (err < 0)
1141*4882a593Smuzhiyun 			break;
1142*4882a593Smuzhiyun 		change |= err;
1143*4882a593Smuzhiyun 	}
1144*4882a593Smuzhiyun 	kcontrol->private_value = pval;
1145*4882a593Smuzhiyun 	mutex_unlock(&codec->control_mutex);
1146*4882a593Smuzhiyun 	return err < 0 ? err : change;
1147*4882a593Smuzhiyun }
1148*4882a593Smuzhiyun 
1149*4882a593Smuzhiyun /* any ctl assigned to the path with the given index? */
path_has_mixer(struct hda_codec * codec,int path_idx,int ctl_type)1150*4882a593Smuzhiyun static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type)
1151*4882a593Smuzhiyun {
1152*4882a593Smuzhiyun 	struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx);
1153*4882a593Smuzhiyun 	return path && path->ctls[ctl_type];
1154*4882a593Smuzhiyun }
1155*4882a593Smuzhiyun 
1156*4882a593Smuzhiyun static const char * const channel_name[4] = {
1157*4882a593Smuzhiyun 	"Front", "Surround", "CLFE", "Side"
1158*4882a593Smuzhiyun };
1159*4882a593Smuzhiyun 
1160*4882a593Smuzhiyun /* give some appropriate ctl name prefix for the given line out channel */
get_line_out_pfx(struct hda_codec * codec,int ch,int * index,int ctl_type)1161*4882a593Smuzhiyun static const char *get_line_out_pfx(struct hda_codec *codec, int ch,
1162*4882a593Smuzhiyun 				    int *index, int ctl_type)
1163*4882a593Smuzhiyun {
1164*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1165*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun 	*index = 0;
1168*4882a593Smuzhiyun 	if (cfg->line_outs == 1 && !spec->multi_ios &&
1169*4882a593Smuzhiyun 	    !codec->force_pin_prefix &&
1170*4882a593Smuzhiyun 	    !cfg->hp_outs && !cfg->speaker_outs)
1171*4882a593Smuzhiyun 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	/* if there is really a single DAC used in the whole output paths,
1174*4882a593Smuzhiyun 	 * use it master (or "PCM" if a vmaster hook is present)
1175*4882a593Smuzhiyun 	 */
1176*4882a593Smuzhiyun 	if (spec->multiout.num_dacs == 1 && !spec->mixer_nid &&
1177*4882a593Smuzhiyun 	    !codec->force_pin_prefix &&
1178*4882a593Smuzhiyun 	    !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0])
1179*4882a593Smuzhiyun 		return spec->vmaster_mute.hook ? "PCM" : "Master";
1180*4882a593Smuzhiyun 
1181*4882a593Smuzhiyun 	/* multi-io channels */
1182*4882a593Smuzhiyun 	if (ch >= cfg->line_outs)
1183*4882a593Smuzhiyun 		return channel_name[ch];
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun 	switch (cfg->line_out_type) {
1186*4882a593Smuzhiyun 	case AUTO_PIN_SPEAKER_OUT:
1187*4882a593Smuzhiyun 		/* if the primary channel vol/mute is shared with HP volume,
1188*4882a593Smuzhiyun 		 * don't name it as Speaker
1189*4882a593Smuzhiyun 		 */
1190*4882a593Smuzhiyun 		if (!ch && cfg->hp_outs &&
1191*4882a593Smuzhiyun 		    !path_has_mixer(codec, spec->hp_paths[0], ctl_type))
1192*4882a593Smuzhiyun 			break;
1193*4882a593Smuzhiyun 		if (cfg->line_outs == 1)
1194*4882a593Smuzhiyun 			return "Speaker";
1195*4882a593Smuzhiyun 		if (cfg->line_outs == 2)
1196*4882a593Smuzhiyun 			return ch ? "Bass Speaker" : "Speaker";
1197*4882a593Smuzhiyun 		break;
1198*4882a593Smuzhiyun 	case AUTO_PIN_HP_OUT:
1199*4882a593Smuzhiyun 		/* if the primary channel vol/mute is shared with spk volume,
1200*4882a593Smuzhiyun 		 * don't name it as Headphone
1201*4882a593Smuzhiyun 		 */
1202*4882a593Smuzhiyun 		if (!ch && cfg->speaker_outs &&
1203*4882a593Smuzhiyun 		    !path_has_mixer(codec, spec->speaker_paths[0], ctl_type))
1204*4882a593Smuzhiyun 			break;
1205*4882a593Smuzhiyun 		/* for multi-io case, only the primary out */
1206*4882a593Smuzhiyun 		if (ch && spec->multi_ios)
1207*4882a593Smuzhiyun 			break;
1208*4882a593Smuzhiyun 		*index = ch;
1209*4882a593Smuzhiyun 		return "Headphone";
1210*4882a593Smuzhiyun 	case AUTO_PIN_LINE_OUT:
1211*4882a593Smuzhiyun 		/* This deals with the case where one HP or one Speaker or
1212*4882a593Smuzhiyun 		 * one HP + one Speaker need to share the DAC with LO
1213*4882a593Smuzhiyun 		 */
1214*4882a593Smuzhiyun 		if (!ch) {
1215*4882a593Smuzhiyun 			bool hp_lo_shared = false, spk_lo_shared = false;
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun 			if (cfg->speaker_outs)
1218*4882a593Smuzhiyun 				spk_lo_shared = !path_has_mixer(codec,
1219*4882a593Smuzhiyun 								spec->speaker_paths[0],	ctl_type);
1220*4882a593Smuzhiyun 			if (cfg->hp_outs)
1221*4882a593Smuzhiyun 				hp_lo_shared = !path_has_mixer(codec, spec->hp_paths[0], ctl_type);
1222*4882a593Smuzhiyun 			if (hp_lo_shared && spk_lo_shared)
1223*4882a593Smuzhiyun 				return spec->vmaster_mute.hook ? "PCM" : "Master";
1224*4882a593Smuzhiyun 			if (hp_lo_shared)
1225*4882a593Smuzhiyun 				return "Headphone+LO";
1226*4882a593Smuzhiyun 			if (spk_lo_shared)
1227*4882a593Smuzhiyun 				return "Speaker+LO";
1228*4882a593Smuzhiyun 		}
1229*4882a593Smuzhiyun 	}
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun 	/* for a single channel output, we don't have to name the channel */
1232*4882a593Smuzhiyun 	if (cfg->line_outs == 1 && !spec->multi_ios)
1233*4882a593Smuzhiyun 		return "Line Out";
1234*4882a593Smuzhiyun 
1235*4882a593Smuzhiyun 	if (ch >= ARRAY_SIZE(channel_name)) {
1236*4882a593Smuzhiyun 		snd_BUG();
1237*4882a593Smuzhiyun 		return "PCM";
1238*4882a593Smuzhiyun 	}
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun 	return channel_name[ch];
1241*4882a593Smuzhiyun }
1242*4882a593Smuzhiyun 
1243*4882a593Smuzhiyun /*
1244*4882a593Smuzhiyun  * Parse output paths
1245*4882a593Smuzhiyun  */
1246*4882a593Smuzhiyun 
1247*4882a593Smuzhiyun /* badness definition */
1248*4882a593Smuzhiyun enum {
1249*4882a593Smuzhiyun 	/* No primary DAC is found for the main output */
1250*4882a593Smuzhiyun 	BAD_NO_PRIMARY_DAC = 0x10000,
1251*4882a593Smuzhiyun 	/* No DAC is found for the extra output */
1252*4882a593Smuzhiyun 	BAD_NO_DAC = 0x4000,
1253*4882a593Smuzhiyun 	/* No possible multi-ios */
1254*4882a593Smuzhiyun 	BAD_MULTI_IO = 0x120,
1255*4882a593Smuzhiyun 	/* No individual DAC for extra output */
1256*4882a593Smuzhiyun 	BAD_NO_EXTRA_DAC = 0x102,
1257*4882a593Smuzhiyun 	/* No individual DAC for extra surrounds */
1258*4882a593Smuzhiyun 	BAD_NO_EXTRA_SURR_DAC = 0x101,
1259*4882a593Smuzhiyun 	/* Primary DAC shared with main surrounds */
1260*4882a593Smuzhiyun 	BAD_SHARED_SURROUND = 0x100,
1261*4882a593Smuzhiyun 	/* No independent HP possible */
1262*4882a593Smuzhiyun 	BAD_NO_INDEP_HP = 0x10,
1263*4882a593Smuzhiyun 	/* Primary DAC shared with main CLFE */
1264*4882a593Smuzhiyun 	BAD_SHARED_CLFE = 0x10,
1265*4882a593Smuzhiyun 	/* Primary DAC shared with extra surrounds */
1266*4882a593Smuzhiyun 	BAD_SHARED_EXTRA_SURROUND = 0x10,
1267*4882a593Smuzhiyun 	/* Volume widget is shared */
1268*4882a593Smuzhiyun 	BAD_SHARED_VOL = 0x10,
1269*4882a593Smuzhiyun };
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun /* look for widgets in the given path which are appropriate for
1272*4882a593Smuzhiyun  * volume and mute controls, and assign the values to ctls[].
1273*4882a593Smuzhiyun  *
1274*4882a593Smuzhiyun  * When no appropriate widget is found in the path, the badness value
1275*4882a593Smuzhiyun  * is incremented depending on the situation.  The function returns the
1276*4882a593Smuzhiyun  * total badness for both volume and mute controls.
1277*4882a593Smuzhiyun  */
assign_out_path_ctls(struct hda_codec * codec,struct nid_path * path)1278*4882a593Smuzhiyun static int assign_out_path_ctls(struct hda_codec *codec, struct nid_path *path)
1279*4882a593Smuzhiyun {
1280*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1281*4882a593Smuzhiyun 	hda_nid_t nid;
1282*4882a593Smuzhiyun 	unsigned int val;
1283*4882a593Smuzhiyun 	int badness = 0;
1284*4882a593Smuzhiyun 
1285*4882a593Smuzhiyun 	if (!path)
1286*4882a593Smuzhiyun 		return BAD_SHARED_VOL * 2;
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun 	if (path->ctls[NID_PATH_VOL_CTL] ||
1289*4882a593Smuzhiyun 	    path->ctls[NID_PATH_MUTE_CTL])
1290*4882a593Smuzhiyun 		return 0; /* already evaluated */
1291*4882a593Smuzhiyun 
1292*4882a593Smuzhiyun 	nid = look_for_out_vol_nid(codec, path);
1293*4882a593Smuzhiyun 	if (nid) {
1294*4882a593Smuzhiyun 		val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1295*4882a593Smuzhiyun 		if (spec->dac_min_mute)
1296*4882a593Smuzhiyun 			val |= HDA_AMP_VAL_MIN_MUTE;
1297*4882a593Smuzhiyun 		if (is_ctl_used(codec, val, NID_PATH_VOL_CTL))
1298*4882a593Smuzhiyun 			badness += BAD_SHARED_VOL;
1299*4882a593Smuzhiyun 		else
1300*4882a593Smuzhiyun 			path->ctls[NID_PATH_VOL_CTL] = val;
1301*4882a593Smuzhiyun 	} else
1302*4882a593Smuzhiyun 		badness += BAD_SHARED_VOL;
1303*4882a593Smuzhiyun 	nid = look_for_out_mute_nid(codec, path);
1304*4882a593Smuzhiyun 	if (nid) {
1305*4882a593Smuzhiyun 		unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
1306*4882a593Smuzhiyun 		if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT ||
1307*4882a593Smuzhiyun 		    nid_has_mute(codec, nid, HDA_OUTPUT))
1308*4882a593Smuzhiyun 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
1309*4882a593Smuzhiyun 		else
1310*4882a593Smuzhiyun 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
1311*4882a593Smuzhiyun 		if (is_ctl_used(codec, val, NID_PATH_MUTE_CTL))
1312*4882a593Smuzhiyun 			badness += BAD_SHARED_VOL;
1313*4882a593Smuzhiyun 		else
1314*4882a593Smuzhiyun 			path->ctls[NID_PATH_MUTE_CTL] = val;
1315*4882a593Smuzhiyun 	} else
1316*4882a593Smuzhiyun 		badness += BAD_SHARED_VOL;
1317*4882a593Smuzhiyun 	return badness;
1318*4882a593Smuzhiyun }
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun const struct badness_table hda_main_out_badness = {
1321*4882a593Smuzhiyun 	.no_primary_dac = BAD_NO_PRIMARY_DAC,
1322*4882a593Smuzhiyun 	.no_dac = BAD_NO_DAC,
1323*4882a593Smuzhiyun 	.shared_primary = BAD_NO_PRIMARY_DAC,
1324*4882a593Smuzhiyun 	.shared_surr = BAD_SHARED_SURROUND,
1325*4882a593Smuzhiyun 	.shared_clfe = BAD_SHARED_CLFE,
1326*4882a593Smuzhiyun 	.shared_surr_main = BAD_SHARED_SURROUND,
1327*4882a593Smuzhiyun };
1328*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(hda_main_out_badness);
1329*4882a593Smuzhiyun 
1330*4882a593Smuzhiyun const struct badness_table hda_extra_out_badness = {
1331*4882a593Smuzhiyun 	.no_primary_dac = BAD_NO_DAC,
1332*4882a593Smuzhiyun 	.no_dac = BAD_NO_DAC,
1333*4882a593Smuzhiyun 	.shared_primary = BAD_NO_EXTRA_DAC,
1334*4882a593Smuzhiyun 	.shared_surr = BAD_SHARED_EXTRA_SURROUND,
1335*4882a593Smuzhiyun 	.shared_clfe = BAD_SHARED_EXTRA_SURROUND,
1336*4882a593Smuzhiyun 	.shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
1337*4882a593Smuzhiyun };
1338*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(hda_extra_out_badness);
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun /* get the DAC of the primary output corresponding to the given array index */
get_primary_out(struct hda_codec * codec,int idx)1341*4882a593Smuzhiyun static hda_nid_t get_primary_out(struct hda_codec *codec, int idx)
1342*4882a593Smuzhiyun {
1343*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1344*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1345*4882a593Smuzhiyun 
1346*4882a593Smuzhiyun 	if (cfg->line_outs > idx)
1347*4882a593Smuzhiyun 		return spec->private_dac_nids[idx];
1348*4882a593Smuzhiyun 	idx -= cfg->line_outs;
1349*4882a593Smuzhiyun 	if (spec->multi_ios > idx)
1350*4882a593Smuzhiyun 		return spec->multi_io[idx].dac;
1351*4882a593Smuzhiyun 	return 0;
1352*4882a593Smuzhiyun }
1353*4882a593Smuzhiyun 
1354*4882a593Smuzhiyun /* return the DAC if it's reachable, otherwise zero */
try_dac(struct hda_codec * codec,hda_nid_t dac,hda_nid_t pin)1355*4882a593Smuzhiyun static inline hda_nid_t try_dac(struct hda_codec *codec,
1356*4882a593Smuzhiyun 				hda_nid_t dac, hda_nid_t pin)
1357*4882a593Smuzhiyun {
1358*4882a593Smuzhiyun 	return is_reachable_path(codec, dac, pin) ? dac : 0;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun /* try to assign DACs to pins and return the resultant badness */
try_assign_dacs(struct hda_codec * codec,int num_outs,const hda_nid_t * pins,hda_nid_t * dacs,int * path_idx,const struct badness_table * bad)1362*4882a593Smuzhiyun static int try_assign_dacs(struct hda_codec *codec, int num_outs,
1363*4882a593Smuzhiyun 			   const hda_nid_t *pins, hda_nid_t *dacs,
1364*4882a593Smuzhiyun 			   int *path_idx,
1365*4882a593Smuzhiyun 			   const struct badness_table *bad)
1366*4882a593Smuzhiyun {
1367*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1368*4882a593Smuzhiyun 	int i, j;
1369*4882a593Smuzhiyun 	int badness = 0;
1370*4882a593Smuzhiyun 	hda_nid_t dac;
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun 	if (!num_outs)
1373*4882a593Smuzhiyun 		return 0;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	for (i = 0; i < num_outs; i++) {
1376*4882a593Smuzhiyun 		struct nid_path *path;
1377*4882a593Smuzhiyun 		hda_nid_t pin = pins[i];
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 		if (!spec->obey_preferred_dacs) {
1380*4882a593Smuzhiyun 			path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1381*4882a593Smuzhiyun 			if (path) {
1382*4882a593Smuzhiyun 				badness += assign_out_path_ctls(codec, path);
1383*4882a593Smuzhiyun 				continue;
1384*4882a593Smuzhiyun 			}
1385*4882a593Smuzhiyun 		}
1386*4882a593Smuzhiyun 
1387*4882a593Smuzhiyun 		dacs[i] = get_preferred_dac(codec, pin);
1388*4882a593Smuzhiyun 		if (dacs[i]) {
1389*4882a593Smuzhiyun 			if (is_dac_already_used(codec, dacs[i]))
1390*4882a593Smuzhiyun 				badness += bad->shared_primary;
1391*4882a593Smuzhiyun 		} else if (spec->obey_preferred_dacs) {
1392*4882a593Smuzhiyun 			badness += BAD_NO_PRIMARY_DAC;
1393*4882a593Smuzhiyun 		}
1394*4882a593Smuzhiyun 
1395*4882a593Smuzhiyun 		if (!dacs[i])
1396*4882a593Smuzhiyun 			dacs[i] = look_for_dac(codec, pin, false);
1397*4882a593Smuzhiyun 		if (!dacs[i] && !i) {
1398*4882a593Smuzhiyun 			/* try to steal the DAC of surrounds for the front */
1399*4882a593Smuzhiyun 			for (j = 1; j < num_outs; j++) {
1400*4882a593Smuzhiyun 				if (is_reachable_path(codec, dacs[j], pin)) {
1401*4882a593Smuzhiyun 					dacs[0] = dacs[j];
1402*4882a593Smuzhiyun 					dacs[j] = 0;
1403*4882a593Smuzhiyun 					invalidate_nid_path(codec, path_idx[j]);
1404*4882a593Smuzhiyun 					path_idx[j] = 0;
1405*4882a593Smuzhiyun 					break;
1406*4882a593Smuzhiyun 				}
1407*4882a593Smuzhiyun 			}
1408*4882a593Smuzhiyun 		}
1409*4882a593Smuzhiyun 		dac = dacs[i];
1410*4882a593Smuzhiyun 		if (!dac) {
1411*4882a593Smuzhiyun 			if (num_outs > 2)
1412*4882a593Smuzhiyun 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1413*4882a593Smuzhiyun 			if (!dac)
1414*4882a593Smuzhiyun 				dac = try_dac(codec, dacs[0], pin);
1415*4882a593Smuzhiyun 			if (!dac)
1416*4882a593Smuzhiyun 				dac = try_dac(codec, get_primary_out(codec, i), pin);
1417*4882a593Smuzhiyun 			if (dac) {
1418*4882a593Smuzhiyun 				if (!i)
1419*4882a593Smuzhiyun 					badness += bad->shared_primary;
1420*4882a593Smuzhiyun 				else if (i == 1)
1421*4882a593Smuzhiyun 					badness += bad->shared_surr;
1422*4882a593Smuzhiyun 				else
1423*4882a593Smuzhiyun 					badness += bad->shared_clfe;
1424*4882a593Smuzhiyun 			} else if (is_reachable_path(codec, spec->private_dac_nids[0], pin)) {
1425*4882a593Smuzhiyun 				dac = spec->private_dac_nids[0];
1426*4882a593Smuzhiyun 				badness += bad->shared_surr_main;
1427*4882a593Smuzhiyun 			} else if (!i)
1428*4882a593Smuzhiyun 				badness += bad->no_primary_dac;
1429*4882a593Smuzhiyun 			else
1430*4882a593Smuzhiyun 				badness += bad->no_dac;
1431*4882a593Smuzhiyun 		}
1432*4882a593Smuzhiyun 		if (!dac)
1433*4882a593Smuzhiyun 			continue;
1434*4882a593Smuzhiyun 		path = snd_hda_add_new_path(codec, dac, pin, -spec->mixer_nid);
1435*4882a593Smuzhiyun 		if (!path && !i && spec->mixer_nid) {
1436*4882a593Smuzhiyun 			/* try with aamix */
1437*4882a593Smuzhiyun 			path = snd_hda_add_new_path(codec, dac, pin, 0);
1438*4882a593Smuzhiyun 		}
1439*4882a593Smuzhiyun 		if (!path) {
1440*4882a593Smuzhiyun 			dac = dacs[i] = 0;
1441*4882a593Smuzhiyun 			badness += bad->no_dac;
1442*4882a593Smuzhiyun 		} else {
1443*4882a593Smuzhiyun 			/* print_nid_path(codec, "output", path); */
1444*4882a593Smuzhiyun 			path->active = true;
1445*4882a593Smuzhiyun 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1446*4882a593Smuzhiyun 			badness += assign_out_path_ctls(codec, path);
1447*4882a593Smuzhiyun 		}
1448*4882a593Smuzhiyun 	}
1449*4882a593Smuzhiyun 
1450*4882a593Smuzhiyun 	return badness;
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun /* return NID if the given pin has only a single connection to a certain DAC */
get_dac_if_single(struct hda_codec * codec,hda_nid_t pin)1454*4882a593Smuzhiyun static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
1455*4882a593Smuzhiyun {
1456*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1457*4882a593Smuzhiyun 	int i;
1458*4882a593Smuzhiyun 	hda_nid_t nid_found = 0;
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun 	for (i = 0; i < spec->num_all_dacs; i++) {
1461*4882a593Smuzhiyun 		hda_nid_t nid = spec->all_dacs[i];
1462*4882a593Smuzhiyun 		if (!nid || is_dac_already_used(codec, nid))
1463*4882a593Smuzhiyun 			continue;
1464*4882a593Smuzhiyun 		if (is_reachable_path(codec, nid, pin)) {
1465*4882a593Smuzhiyun 			if (nid_found)
1466*4882a593Smuzhiyun 				return 0;
1467*4882a593Smuzhiyun 			nid_found = nid;
1468*4882a593Smuzhiyun 		}
1469*4882a593Smuzhiyun 	}
1470*4882a593Smuzhiyun 	return nid_found;
1471*4882a593Smuzhiyun }
1472*4882a593Smuzhiyun 
1473*4882a593Smuzhiyun /* check whether the given pin can be a multi-io pin */
can_be_multiio_pin(struct hda_codec * codec,unsigned int location,hda_nid_t nid)1474*4882a593Smuzhiyun static bool can_be_multiio_pin(struct hda_codec *codec,
1475*4882a593Smuzhiyun 			       unsigned int location, hda_nid_t nid)
1476*4882a593Smuzhiyun {
1477*4882a593Smuzhiyun 	unsigned int defcfg, caps;
1478*4882a593Smuzhiyun 
1479*4882a593Smuzhiyun 	defcfg = snd_hda_codec_get_pincfg(codec, nid);
1480*4882a593Smuzhiyun 	if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
1481*4882a593Smuzhiyun 		return false;
1482*4882a593Smuzhiyun 	if (location && get_defcfg_location(defcfg) != location)
1483*4882a593Smuzhiyun 		return false;
1484*4882a593Smuzhiyun 	caps = snd_hda_query_pin_caps(codec, nid);
1485*4882a593Smuzhiyun 	if (!(caps & AC_PINCAP_OUT))
1486*4882a593Smuzhiyun 		return false;
1487*4882a593Smuzhiyun 	return true;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun /* count the number of input pins that are capable to be multi-io */
count_multiio_pins(struct hda_codec * codec,hda_nid_t reference_pin)1491*4882a593Smuzhiyun static int count_multiio_pins(struct hda_codec *codec, hda_nid_t reference_pin)
1492*4882a593Smuzhiyun {
1493*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1494*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1495*4882a593Smuzhiyun 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1496*4882a593Smuzhiyun 	unsigned int location = get_defcfg_location(defcfg);
1497*4882a593Smuzhiyun 	int type, i;
1498*4882a593Smuzhiyun 	int num_pins = 0;
1499*4882a593Smuzhiyun 
1500*4882a593Smuzhiyun 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1501*4882a593Smuzhiyun 		for (i = 0; i < cfg->num_inputs; i++) {
1502*4882a593Smuzhiyun 			if (cfg->inputs[i].type != type)
1503*4882a593Smuzhiyun 				continue;
1504*4882a593Smuzhiyun 			if (can_be_multiio_pin(codec, location,
1505*4882a593Smuzhiyun 					       cfg->inputs[i].pin))
1506*4882a593Smuzhiyun 				num_pins++;
1507*4882a593Smuzhiyun 		}
1508*4882a593Smuzhiyun 	}
1509*4882a593Smuzhiyun 	return num_pins;
1510*4882a593Smuzhiyun }
1511*4882a593Smuzhiyun 
1512*4882a593Smuzhiyun /*
1513*4882a593Smuzhiyun  * multi-io helper
1514*4882a593Smuzhiyun  *
1515*4882a593Smuzhiyun  * When hardwired is set, try to fill ony hardwired pins, and returns
1516*4882a593Smuzhiyun  * zero if any pins are filled, non-zero if nothing found.
1517*4882a593Smuzhiyun  * When hardwired is off, try to fill possible input pins, and returns
1518*4882a593Smuzhiyun  * the badness value.
1519*4882a593Smuzhiyun  */
fill_multi_ios(struct hda_codec * codec,hda_nid_t reference_pin,bool hardwired)1520*4882a593Smuzhiyun static int fill_multi_ios(struct hda_codec *codec,
1521*4882a593Smuzhiyun 			  hda_nid_t reference_pin,
1522*4882a593Smuzhiyun 			  bool hardwired)
1523*4882a593Smuzhiyun {
1524*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1525*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1526*4882a593Smuzhiyun 	int type, i, j, num_pins, old_pins;
1527*4882a593Smuzhiyun 	unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
1528*4882a593Smuzhiyun 	unsigned int location = get_defcfg_location(defcfg);
1529*4882a593Smuzhiyun 	int badness = 0;
1530*4882a593Smuzhiyun 	struct nid_path *path;
1531*4882a593Smuzhiyun 
1532*4882a593Smuzhiyun 	old_pins = spec->multi_ios;
1533*4882a593Smuzhiyun 	if (old_pins >= 2)
1534*4882a593Smuzhiyun 		goto end_fill;
1535*4882a593Smuzhiyun 
1536*4882a593Smuzhiyun 	num_pins = count_multiio_pins(codec, reference_pin);
1537*4882a593Smuzhiyun 	if (num_pins < 2)
1538*4882a593Smuzhiyun 		goto end_fill;
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun 	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
1541*4882a593Smuzhiyun 		for (i = 0; i < cfg->num_inputs; i++) {
1542*4882a593Smuzhiyun 			hda_nid_t nid = cfg->inputs[i].pin;
1543*4882a593Smuzhiyun 			hda_nid_t dac = 0;
1544*4882a593Smuzhiyun 
1545*4882a593Smuzhiyun 			if (cfg->inputs[i].type != type)
1546*4882a593Smuzhiyun 				continue;
1547*4882a593Smuzhiyun 			if (!can_be_multiio_pin(codec, location, nid))
1548*4882a593Smuzhiyun 				continue;
1549*4882a593Smuzhiyun 			for (j = 0; j < spec->multi_ios; j++) {
1550*4882a593Smuzhiyun 				if (nid == spec->multi_io[j].pin)
1551*4882a593Smuzhiyun 					break;
1552*4882a593Smuzhiyun 			}
1553*4882a593Smuzhiyun 			if (j < spec->multi_ios)
1554*4882a593Smuzhiyun 				continue;
1555*4882a593Smuzhiyun 
1556*4882a593Smuzhiyun 			if (hardwired)
1557*4882a593Smuzhiyun 				dac = get_dac_if_single(codec, nid);
1558*4882a593Smuzhiyun 			else if (!dac)
1559*4882a593Smuzhiyun 				dac = look_for_dac(codec, nid, false);
1560*4882a593Smuzhiyun 			if (!dac) {
1561*4882a593Smuzhiyun 				badness++;
1562*4882a593Smuzhiyun 				continue;
1563*4882a593Smuzhiyun 			}
1564*4882a593Smuzhiyun 			path = snd_hda_add_new_path(codec, dac, nid,
1565*4882a593Smuzhiyun 						    -spec->mixer_nid);
1566*4882a593Smuzhiyun 			if (!path) {
1567*4882a593Smuzhiyun 				badness++;
1568*4882a593Smuzhiyun 				continue;
1569*4882a593Smuzhiyun 			}
1570*4882a593Smuzhiyun 			/* print_nid_path(codec, "multiio", path); */
1571*4882a593Smuzhiyun 			spec->multi_io[spec->multi_ios].pin = nid;
1572*4882a593Smuzhiyun 			spec->multi_io[spec->multi_ios].dac = dac;
1573*4882a593Smuzhiyun 			spec->out_paths[cfg->line_outs + spec->multi_ios] =
1574*4882a593Smuzhiyun 				snd_hda_get_path_idx(codec, path);
1575*4882a593Smuzhiyun 			spec->multi_ios++;
1576*4882a593Smuzhiyun 			if (spec->multi_ios >= 2)
1577*4882a593Smuzhiyun 				break;
1578*4882a593Smuzhiyun 		}
1579*4882a593Smuzhiyun 	}
1580*4882a593Smuzhiyun  end_fill:
1581*4882a593Smuzhiyun 	if (badness)
1582*4882a593Smuzhiyun 		badness = BAD_MULTI_IO;
1583*4882a593Smuzhiyun 	if (old_pins == spec->multi_ios) {
1584*4882a593Smuzhiyun 		if (hardwired)
1585*4882a593Smuzhiyun 			return 1; /* nothing found */
1586*4882a593Smuzhiyun 		else
1587*4882a593Smuzhiyun 			return badness; /* no badness if nothing found */
1588*4882a593Smuzhiyun 	}
1589*4882a593Smuzhiyun 	if (!hardwired && spec->multi_ios < 2) {
1590*4882a593Smuzhiyun 		/* cancel newly assigned paths */
1591*4882a593Smuzhiyun 		spec->paths.used -= spec->multi_ios - old_pins;
1592*4882a593Smuzhiyun 		spec->multi_ios = old_pins;
1593*4882a593Smuzhiyun 		return badness;
1594*4882a593Smuzhiyun 	}
1595*4882a593Smuzhiyun 
1596*4882a593Smuzhiyun 	/* assign volume and mute controls */
1597*4882a593Smuzhiyun 	for (i = old_pins; i < spec->multi_ios; i++) {
1598*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[cfg->line_outs + i]);
1599*4882a593Smuzhiyun 		badness += assign_out_path_ctls(codec, path);
1600*4882a593Smuzhiyun 	}
1601*4882a593Smuzhiyun 
1602*4882a593Smuzhiyun 	return badness;
1603*4882a593Smuzhiyun }
1604*4882a593Smuzhiyun 
1605*4882a593Smuzhiyun /* map DACs for all pins in the list if they are single connections */
map_singles(struct hda_codec * codec,int outs,const hda_nid_t * pins,hda_nid_t * dacs,int * path_idx)1606*4882a593Smuzhiyun static bool map_singles(struct hda_codec *codec, int outs,
1607*4882a593Smuzhiyun 			const hda_nid_t *pins, hda_nid_t *dacs, int *path_idx)
1608*4882a593Smuzhiyun {
1609*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1610*4882a593Smuzhiyun 	int i;
1611*4882a593Smuzhiyun 	bool found = false;
1612*4882a593Smuzhiyun 	for (i = 0; i < outs; i++) {
1613*4882a593Smuzhiyun 		struct nid_path *path;
1614*4882a593Smuzhiyun 		hda_nid_t dac;
1615*4882a593Smuzhiyun 		if (dacs[i])
1616*4882a593Smuzhiyun 			continue;
1617*4882a593Smuzhiyun 		dac = get_dac_if_single(codec, pins[i]);
1618*4882a593Smuzhiyun 		if (!dac)
1619*4882a593Smuzhiyun 			continue;
1620*4882a593Smuzhiyun 		path = snd_hda_add_new_path(codec, dac, pins[i],
1621*4882a593Smuzhiyun 					    -spec->mixer_nid);
1622*4882a593Smuzhiyun 		if (!path && !i && spec->mixer_nid)
1623*4882a593Smuzhiyun 			path = snd_hda_add_new_path(codec, dac, pins[i], 0);
1624*4882a593Smuzhiyun 		if (path) {
1625*4882a593Smuzhiyun 			dacs[i] = dac;
1626*4882a593Smuzhiyun 			found = true;
1627*4882a593Smuzhiyun 			/* print_nid_path(codec, "output", path); */
1628*4882a593Smuzhiyun 			path->active = true;
1629*4882a593Smuzhiyun 			path_idx[i] = snd_hda_get_path_idx(codec, path);
1630*4882a593Smuzhiyun 		}
1631*4882a593Smuzhiyun 	}
1632*4882a593Smuzhiyun 	return found;
1633*4882a593Smuzhiyun }
1634*4882a593Smuzhiyun 
has_aamix_out_paths(struct hda_gen_spec * spec)1635*4882a593Smuzhiyun static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
1636*4882a593Smuzhiyun {
1637*4882a593Smuzhiyun 	return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
1638*4882a593Smuzhiyun 		spec->aamix_out_paths[2];
1639*4882a593Smuzhiyun }
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun /* create a new path including aamix if available, and return its index */
check_aamix_out_path(struct hda_codec * codec,int path_idx)1642*4882a593Smuzhiyun static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
1643*4882a593Smuzhiyun {
1644*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1645*4882a593Smuzhiyun 	struct nid_path *path;
1646*4882a593Smuzhiyun 	hda_nid_t path_dac, dac, pin;
1647*4882a593Smuzhiyun 
1648*4882a593Smuzhiyun 	path = snd_hda_get_path_from_idx(codec, path_idx);
1649*4882a593Smuzhiyun 	if (!path || !path->depth ||
1650*4882a593Smuzhiyun 	    is_nid_contained(path, spec->mixer_nid))
1651*4882a593Smuzhiyun 		return 0;
1652*4882a593Smuzhiyun 	path_dac = path->path[0];
1653*4882a593Smuzhiyun 	dac = spec->private_dac_nids[0];
1654*4882a593Smuzhiyun 	pin = path->path[path->depth - 1];
1655*4882a593Smuzhiyun 	path = snd_hda_add_new_path(codec, dac, pin, spec->mixer_nid);
1656*4882a593Smuzhiyun 	if (!path) {
1657*4882a593Smuzhiyun 		if (dac != path_dac)
1658*4882a593Smuzhiyun 			dac = path_dac;
1659*4882a593Smuzhiyun 		else if (spec->multiout.hp_out_nid[0])
1660*4882a593Smuzhiyun 			dac = spec->multiout.hp_out_nid[0];
1661*4882a593Smuzhiyun 		else if (spec->multiout.extra_out_nid[0])
1662*4882a593Smuzhiyun 			dac = spec->multiout.extra_out_nid[0];
1663*4882a593Smuzhiyun 		else
1664*4882a593Smuzhiyun 			dac = 0;
1665*4882a593Smuzhiyun 		if (dac)
1666*4882a593Smuzhiyun 			path = snd_hda_add_new_path(codec, dac, pin,
1667*4882a593Smuzhiyun 						    spec->mixer_nid);
1668*4882a593Smuzhiyun 	}
1669*4882a593Smuzhiyun 	if (!path)
1670*4882a593Smuzhiyun 		return 0;
1671*4882a593Smuzhiyun 	/* print_nid_path(codec, "output-aamix", path); */
1672*4882a593Smuzhiyun 	path->active = false; /* unused as default */
1673*4882a593Smuzhiyun 	path->pin_fixed = true; /* static route */
1674*4882a593Smuzhiyun 	return snd_hda_get_path_idx(codec, path);
1675*4882a593Smuzhiyun }
1676*4882a593Smuzhiyun 
1677*4882a593Smuzhiyun /* check whether the independent HP is available with the current config */
indep_hp_possible(struct hda_codec * codec)1678*4882a593Smuzhiyun static bool indep_hp_possible(struct hda_codec *codec)
1679*4882a593Smuzhiyun {
1680*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1681*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1682*4882a593Smuzhiyun 	struct nid_path *path;
1683*4882a593Smuzhiyun 	int i, idx;
1684*4882a593Smuzhiyun 
1685*4882a593Smuzhiyun 	if (cfg->line_out_type == AUTO_PIN_HP_OUT)
1686*4882a593Smuzhiyun 		idx = spec->out_paths[0];
1687*4882a593Smuzhiyun 	else
1688*4882a593Smuzhiyun 		idx = spec->hp_paths[0];
1689*4882a593Smuzhiyun 	path = snd_hda_get_path_from_idx(codec, idx);
1690*4882a593Smuzhiyun 	if (!path)
1691*4882a593Smuzhiyun 		return false;
1692*4882a593Smuzhiyun 
1693*4882a593Smuzhiyun 	/* assume no path conflicts unless aamix is involved */
1694*4882a593Smuzhiyun 	if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
1695*4882a593Smuzhiyun 		return true;
1696*4882a593Smuzhiyun 
1697*4882a593Smuzhiyun 	/* check whether output paths contain aamix */
1698*4882a593Smuzhiyun 	for (i = 0; i < cfg->line_outs; i++) {
1699*4882a593Smuzhiyun 		if (spec->out_paths[i] == idx)
1700*4882a593Smuzhiyun 			break;
1701*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
1702*4882a593Smuzhiyun 		if (path && is_nid_contained(path, spec->mixer_nid))
1703*4882a593Smuzhiyun 			return false;
1704*4882a593Smuzhiyun 	}
1705*4882a593Smuzhiyun 	for (i = 0; i < cfg->speaker_outs; i++) {
1706*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
1707*4882a593Smuzhiyun 		if (path && is_nid_contained(path, spec->mixer_nid))
1708*4882a593Smuzhiyun 			return false;
1709*4882a593Smuzhiyun 	}
1710*4882a593Smuzhiyun 
1711*4882a593Smuzhiyun 	return true;
1712*4882a593Smuzhiyun }
1713*4882a593Smuzhiyun 
1714*4882a593Smuzhiyun /* fill the empty entries in the dac array for speaker/hp with the
1715*4882a593Smuzhiyun  * shared dac pointed by the paths
1716*4882a593Smuzhiyun  */
refill_shared_dacs(struct hda_codec * codec,int num_outs,hda_nid_t * dacs,int * path_idx)1717*4882a593Smuzhiyun static void refill_shared_dacs(struct hda_codec *codec, int num_outs,
1718*4882a593Smuzhiyun 			       hda_nid_t *dacs, int *path_idx)
1719*4882a593Smuzhiyun {
1720*4882a593Smuzhiyun 	struct nid_path *path;
1721*4882a593Smuzhiyun 	int i;
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun 	for (i = 0; i < num_outs; i++) {
1724*4882a593Smuzhiyun 		if (dacs[i])
1725*4882a593Smuzhiyun 			continue;
1726*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, path_idx[i]);
1727*4882a593Smuzhiyun 		if (!path)
1728*4882a593Smuzhiyun 			continue;
1729*4882a593Smuzhiyun 		dacs[i] = path->path[0];
1730*4882a593Smuzhiyun 	}
1731*4882a593Smuzhiyun }
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun /* fill in the dac_nids table from the parsed pin configuration */
fill_and_eval_dacs(struct hda_codec * codec,bool fill_hardwired,bool fill_mio_first)1734*4882a593Smuzhiyun static int fill_and_eval_dacs(struct hda_codec *codec,
1735*4882a593Smuzhiyun 			      bool fill_hardwired,
1736*4882a593Smuzhiyun 			      bool fill_mio_first)
1737*4882a593Smuzhiyun {
1738*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1739*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1740*4882a593Smuzhiyun 	int i, err, badness;
1741*4882a593Smuzhiyun 
1742*4882a593Smuzhiyun 	/* set num_dacs once to full for look_for_dac() */
1743*4882a593Smuzhiyun 	spec->multiout.num_dacs = cfg->line_outs;
1744*4882a593Smuzhiyun 	spec->multiout.dac_nids = spec->private_dac_nids;
1745*4882a593Smuzhiyun 	memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
1746*4882a593Smuzhiyun 	memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
1747*4882a593Smuzhiyun 	memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
1748*4882a593Smuzhiyun 	spec->multi_ios = 0;
1749*4882a593Smuzhiyun 	snd_array_free(&spec->paths);
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun 	/* clear path indices */
1752*4882a593Smuzhiyun 	memset(spec->out_paths, 0, sizeof(spec->out_paths));
1753*4882a593Smuzhiyun 	memset(spec->hp_paths, 0, sizeof(spec->hp_paths));
1754*4882a593Smuzhiyun 	memset(spec->speaker_paths, 0, sizeof(spec->speaker_paths));
1755*4882a593Smuzhiyun 	memset(spec->aamix_out_paths, 0, sizeof(spec->aamix_out_paths));
1756*4882a593Smuzhiyun 	memset(spec->digout_paths, 0, sizeof(spec->digout_paths));
1757*4882a593Smuzhiyun 	memset(spec->input_paths, 0, sizeof(spec->input_paths));
1758*4882a593Smuzhiyun 	memset(spec->loopback_paths, 0, sizeof(spec->loopback_paths));
1759*4882a593Smuzhiyun 	memset(&spec->digin_path, 0, sizeof(spec->digin_path));
1760*4882a593Smuzhiyun 
1761*4882a593Smuzhiyun 	badness = 0;
1762*4882a593Smuzhiyun 
1763*4882a593Smuzhiyun 	/* fill hard-wired DACs first */
1764*4882a593Smuzhiyun 	if (fill_hardwired) {
1765*4882a593Smuzhiyun 		bool mapped;
1766*4882a593Smuzhiyun 		do {
1767*4882a593Smuzhiyun 			mapped = map_singles(codec, cfg->line_outs,
1768*4882a593Smuzhiyun 					     cfg->line_out_pins,
1769*4882a593Smuzhiyun 					     spec->private_dac_nids,
1770*4882a593Smuzhiyun 					     spec->out_paths);
1771*4882a593Smuzhiyun 			mapped |= map_singles(codec, cfg->hp_outs,
1772*4882a593Smuzhiyun 					      cfg->hp_pins,
1773*4882a593Smuzhiyun 					      spec->multiout.hp_out_nid,
1774*4882a593Smuzhiyun 					      spec->hp_paths);
1775*4882a593Smuzhiyun 			mapped |= map_singles(codec, cfg->speaker_outs,
1776*4882a593Smuzhiyun 					      cfg->speaker_pins,
1777*4882a593Smuzhiyun 					      spec->multiout.extra_out_nid,
1778*4882a593Smuzhiyun 					      spec->speaker_paths);
1779*4882a593Smuzhiyun 			if (!spec->no_multi_io &&
1780*4882a593Smuzhiyun 			    fill_mio_first && cfg->line_outs == 1 &&
1781*4882a593Smuzhiyun 			    cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1782*4882a593Smuzhiyun 				err = fill_multi_ios(codec, cfg->line_out_pins[0], true);
1783*4882a593Smuzhiyun 				if (!err)
1784*4882a593Smuzhiyun 					mapped = true;
1785*4882a593Smuzhiyun 			}
1786*4882a593Smuzhiyun 		} while (mapped);
1787*4882a593Smuzhiyun 	}
1788*4882a593Smuzhiyun 
1789*4882a593Smuzhiyun 	badness += try_assign_dacs(codec, cfg->line_outs, cfg->line_out_pins,
1790*4882a593Smuzhiyun 				   spec->private_dac_nids, spec->out_paths,
1791*4882a593Smuzhiyun 				   spec->main_out_badness);
1792*4882a593Smuzhiyun 
1793*4882a593Smuzhiyun 	if (!spec->no_multi_io && fill_mio_first &&
1794*4882a593Smuzhiyun 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1795*4882a593Smuzhiyun 		/* try to fill multi-io first */
1796*4882a593Smuzhiyun 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1797*4882a593Smuzhiyun 		if (err < 0)
1798*4882a593Smuzhiyun 			return err;
1799*4882a593Smuzhiyun 		/* we don't count badness at this stage yet */
1800*4882a593Smuzhiyun 	}
1801*4882a593Smuzhiyun 
1802*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
1803*4882a593Smuzhiyun 		err = try_assign_dacs(codec, cfg->hp_outs, cfg->hp_pins,
1804*4882a593Smuzhiyun 				      spec->multiout.hp_out_nid,
1805*4882a593Smuzhiyun 				      spec->hp_paths,
1806*4882a593Smuzhiyun 				      spec->extra_out_badness);
1807*4882a593Smuzhiyun 		if (err < 0)
1808*4882a593Smuzhiyun 			return err;
1809*4882a593Smuzhiyun 		badness += err;
1810*4882a593Smuzhiyun 	}
1811*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1812*4882a593Smuzhiyun 		err = try_assign_dacs(codec, cfg->speaker_outs,
1813*4882a593Smuzhiyun 				      cfg->speaker_pins,
1814*4882a593Smuzhiyun 				      spec->multiout.extra_out_nid,
1815*4882a593Smuzhiyun 				      spec->speaker_paths,
1816*4882a593Smuzhiyun 				      spec->extra_out_badness);
1817*4882a593Smuzhiyun 		if (err < 0)
1818*4882a593Smuzhiyun 			return err;
1819*4882a593Smuzhiyun 		badness += err;
1820*4882a593Smuzhiyun 	}
1821*4882a593Smuzhiyun 	if (!spec->no_multi_io &&
1822*4882a593Smuzhiyun 	    cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
1823*4882a593Smuzhiyun 		err = fill_multi_ios(codec, cfg->line_out_pins[0], false);
1824*4882a593Smuzhiyun 		if (err < 0)
1825*4882a593Smuzhiyun 			return err;
1826*4882a593Smuzhiyun 		badness += err;
1827*4882a593Smuzhiyun 	}
1828*4882a593Smuzhiyun 
1829*4882a593Smuzhiyun 	if (spec->mixer_nid) {
1830*4882a593Smuzhiyun 		spec->aamix_out_paths[0] =
1831*4882a593Smuzhiyun 			check_aamix_out_path(codec, spec->out_paths[0]);
1832*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1833*4882a593Smuzhiyun 			spec->aamix_out_paths[1] =
1834*4882a593Smuzhiyun 				check_aamix_out_path(codec, spec->hp_paths[0]);
1835*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1836*4882a593Smuzhiyun 			spec->aamix_out_paths[2] =
1837*4882a593Smuzhiyun 				check_aamix_out_path(codec, spec->speaker_paths[0]);
1838*4882a593Smuzhiyun 	}
1839*4882a593Smuzhiyun 
1840*4882a593Smuzhiyun 	if (!spec->no_multi_io &&
1841*4882a593Smuzhiyun 	    cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
1842*4882a593Smuzhiyun 		if (count_multiio_pins(codec, cfg->hp_pins[0]) >= 2)
1843*4882a593Smuzhiyun 			spec->multi_ios = 1; /* give badness */
1844*4882a593Smuzhiyun 
1845*4882a593Smuzhiyun 	/* re-count num_dacs and squash invalid entries */
1846*4882a593Smuzhiyun 	spec->multiout.num_dacs = 0;
1847*4882a593Smuzhiyun 	for (i = 0; i < cfg->line_outs; i++) {
1848*4882a593Smuzhiyun 		if (spec->private_dac_nids[i])
1849*4882a593Smuzhiyun 			spec->multiout.num_dacs++;
1850*4882a593Smuzhiyun 		else {
1851*4882a593Smuzhiyun 			memmove(spec->private_dac_nids + i,
1852*4882a593Smuzhiyun 				spec->private_dac_nids + i + 1,
1853*4882a593Smuzhiyun 				sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
1854*4882a593Smuzhiyun 			spec->private_dac_nids[cfg->line_outs - 1] = 0;
1855*4882a593Smuzhiyun 		}
1856*4882a593Smuzhiyun 	}
1857*4882a593Smuzhiyun 
1858*4882a593Smuzhiyun 	spec->ext_channel_count = spec->min_channel_count =
1859*4882a593Smuzhiyun 		spec->multiout.num_dacs * 2;
1860*4882a593Smuzhiyun 
1861*4882a593Smuzhiyun 	if (spec->multi_ios == 2) {
1862*4882a593Smuzhiyun 		for (i = 0; i < 2; i++)
1863*4882a593Smuzhiyun 			spec->private_dac_nids[spec->multiout.num_dacs++] =
1864*4882a593Smuzhiyun 				spec->multi_io[i].dac;
1865*4882a593Smuzhiyun 	} else if (spec->multi_ios) {
1866*4882a593Smuzhiyun 		spec->multi_ios = 0;
1867*4882a593Smuzhiyun 		badness += BAD_MULTI_IO;
1868*4882a593Smuzhiyun 	}
1869*4882a593Smuzhiyun 
1870*4882a593Smuzhiyun 	if (spec->indep_hp && !indep_hp_possible(codec))
1871*4882a593Smuzhiyun 		badness += BAD_NO_INDEP_HP;
1872*4882a593Smuzhiyun 
1873*4882a593Smuzhiyun 	/* re-fill the shared DAC for speaker / headphone */
1874*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
1875*4882a593Smuzhiyun 		refill_shared_dacs(codec, cfg->hp_outs,
1876*4882a593Smuzhiyun 				   spec->multiout.hp_out_nid,
1877*4882a593Smuzhiyun 				   spec->hp_paths);
1878*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
1879*4882a593Smuzhiyun 		refill_shared_dacs(codec, cfg->speaker_outs,
1880*4882a593Smuzhiyun 				   spec->multiout.extra_out_nid,
1881*4882a593Smuzhiyun 				   spec->speaker_paths);
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun 	return badness;
1884*4882a593Smuzhiyun }
1885*4882a593Smuzhiyun 
1886*4882a593Smuzhiyun #define DEBUG_BADNESS
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun #ifdef DEBUG_BADNESS
1889*4882a593Smuzhiyun #define debug_badness(fmt, ...)						\
1890*4882a593Smuzhiyun 	codec_dbg(codec, fmt, ##__VA_ARGS__)
1891*4882a593Smuzhiyun #else
1892*4882a593Smuzhiyun #define debug_badness(fmt, ...)						\
1893*4882a593Smuzhiyun 	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
1894*4882a593Smuzhiyun #endif
1895*4882a593Smuzhiyun 
1896*4882a593Smuzhiyun #ifdef DEBUG_BADNESS
print_nid_path_idx(struct hda_codec * codec,const char * pfx,int idx)1897*4882a593Smuzhiyun static inline void print_nid_path_idx(struct hda_codec *codec,
1898*4882a593Smuzhiyun 				      const char *pfx, int idx)
1899*4882a593Smuzhiyun {
1900*4882a593Smuzhiyun 	struct nid_path *path;
1901*4882a593Smuzhiyun 
1902*4882a593Smuzhiyun 	path = snd_hda_get_path_from_idx(codec, idx);
1903*4882a593Smuzhiyun 	if (path)
1904*4882a593Smuzhiyun 		print_nid_path(codec, pfx, path);
1905*4882a593Smuzhiyun }
1906*4882a593Smuzhiyun 
debug_show_configs(struct hda_codec * codec,struct auto_pin_cfg * cfg)1907*4882a593Smuzhiyun static void debug_show_configs(struct hda_codec *codec,
1908*4882a593Smuzhiyun 			       struct auto_pin_cfg *cfg)
1909*4882a593Smuzhiyun {
1910*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1911*4882a593Smuzhiyun 	static const char * const lo_type[3] = { "LO", "SP", "HP" };
1912*4882a593Smuzhiyun 	int i;
1913*4882a593Smuzhiyun 
1914*4882a593Smuzhiyun 	debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x (type %s)\n",
1915*4882a593Smuzhiyun 		      cfg->line_out_pins[0], cfg->line_out_pins[1],
1916*4882a593Smuzhiyun 		      cfg->line_out_pins[2], cfg->line_out_pins[3],
1917*4882a593Smuzhiyun 		      spec->multiout.dac_nids[0],
1918*4882a593Smuzhiyun 		      spec->multiout.dac_nids[1],
1919*4882a593Smuzhiyun 		      spec->multiout.dac_nids[2],
1920*4882a593Smuzhiyun 		      spec->multiout.dac_nids[3],
1921*4882a593Smuzhiyun 		      lo_type[cfg->line_out_type]);
1922*4882a593Smuzhiyun 	for (i = 0; i < cfg->line_outs; i++)
1923*4882a593Smuzhiyun 		print_nid_path_idx(codec, "  out", spec->out_paths[i]);
1924*4882a593Smuzhiyun 	if (spec->multi_ios > 0)
1925*4882a593Smuzhiyun 		debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
1926*4882a593Smuzhiyun 			      spec->multi_ios,
1927*4882a593Smuzhiyun 			      spec->multi_io[0].pin, spec->multi_io[1].pin,
1928*4882a593Smuzhiyun 			      spec->multi_io[0].dac, spec->multi_io[1].dac);
1929*4882a593Smuzhiyun 	for (i = 0; i < spec->multi_ios; i++)
1930*4882a593Smuzhiyun 		print_nid_path_idx(codec, "  mio",
1931*4882a593Smuzhiyun 				   spec->out_paths[cfg->line_outs + i]);
1932*4882a593Smuzhiyun 	if (cfg->hp_outs)
1933*4882a593Smuzhiyun 		debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1934*4882a593Smuzhiyun 		      cfg->hp_pins[0], cfg->hp_pins[1],
1935*4882a593Smuzhiyun 		      cfg->hp_pins[2], cfg->hp_pins[3],
1936*4882a593Smuzhiyun 		      spec->multiout.hp_out_nid[0],
1937*4882a593Smuzhiyun 		      spec->multiout.hp_out_nid[1],
1938*4882a593Smuzhiyun 		      spec->multiout.hp_out_nid[2],
1939*4882a593Smuzhiyun 		      spec->multiout.hp_out_nid[3]);
1940*4882a593Smuzhiyun 	for (i = 0; i < cfg->hp_outs; i++)
1941*4882a593Smuzhiyun 		print_nid_path_idx(codec, "  hp ", spec->hp_paths[i]);
1942*4882a593Smuzhiyun 	if (cfg->speaker_outs)
1943*4882a593Smuzhiyun 		debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
1944*4882a593Smuzhiyun 		      cfg->speaker_pins[0], cfg->speaker_pins[1],
1945*4882a593Smuzhiyun 		      cfg->speaker_pins[2], cfg->speaker_pins[3],
1946*4882a593Smuzhiyun 		      spec->multiout.extra_out_nid[0],
1947*4882a593Smuzhiyun 		      spec->multiout.extra_out_nid[1],
1948*4882a593Smuzhiyun 		      spec->multiout.extra_out_nid[2],
1949*4882a593Smuzhiyun 		      spec->multiout.extra_out_nid[3]);
1950*4882a593Smuzhiyun 	for (i = 0; i < cfg->speaker_outs; i++)
1951*4882a593Smuzhiyun 		print_nid_path_idx(codec, "  spk", spec->speaker_paths[i]);
1952*4882a593Smuzhiyun 	for (i = 0; i < 3; i++)
1953*4882a593Smuzhiyun 		print_nid_path_idx(codec, "  mix", spec->aamix_out_paths[i]);
1954*4882a593Smuzhiyun }
1955*4882a593Smuzhiyun #else
1956*4882a593Smuzhiyun #define debug_show_configs(codec, cfg) /* NOP */
1957*4882a593Smuzhiyun #endif
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun /* find all available DACs of the codec */
fill_all_dac_nids(struct hda_codec * codec)1960*4882a593Smuzhiyun static void fill_all_dac_nids(struct hda_codec *codec)
1961*4882a593Smuzhiyun {
1962*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1963*4882a593Smuzhiyun 	hda_nid_t nid;
1964*4882a593Smuzhiyun 
1965*4882a593Smuzhiyun 	spec->num_all_dacs = 0;
1966*4882a593Smuzhiyun 	memset(spec->all_dacs, 0, sizeof(spec->all_dacs));
1967*4882a593Smuzhiyun 	for_each_hda_codec_node(nid, codec) {
1968*4882a593Smuzhiyun 		if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_AUD_OUT)
1969*4882a593Smuzhiyun 			continue;
1970*4882a593Smuzhiyun 		if (spec->num_all_dacs >= ARRAY_SIZE(spec->all_dacs)) {
1971*4882a593Smuzhiyun 			codec_err(codec, "Too many DACs!\n");
1972*4882a593Smuzhiyun 			break;
1973*4882a593Smuzhiyun 		}
1974*4882a593Smuzhiyun 		spec->all_dacs[spec->num_all_dacs++] = nid;
1975*4882a593Smuzhiyun 	}
1976*4882a593Smuzhiyun }
1977*4882a593Smuzhiyun 
parse_output_paths(struct hda_codec * codec)1978*4882a593Smuzhiyun static int parse_output_paths(struct hda_codec *codec)
1979*4882a593Smuzhiyun {
1980*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
1981*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
1982*4882a593Smuzhiyun 	struct auto_pin_cfg *best_cfg;
1983*4882a593Smuzhiyun 	unsigned int val;
1984*4882a593Smuzhiyun 	int best_badness = INT_MAX;
1985*4882a593Smuzhiyun 	int badness;
1986*4882a593Smuzhiyun 	bool fill_hardwired = true, fill_mio_first = true;
1987*4882a593Smuzhiyun 	bool best_wired = true, best_mio = true;
1988*4882a593Smuzhiyun 	bool hp_spk_swapped = false;
1989*4882a593Smuzhiyun 
1990*4882a593Smuzhiyun 	best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
1991*4882a593Smuzhiyun 	if (!best_cfg)
1992*4882a593Smuzhiyun 		return -ENOMEM;
1993*4882a593Smuzhiyun 	*best_cfg = *cfg;
1994*4882a593Smuzhiyun 
1995*4882a593Smuzhiyun 	for (;;) {
1996*4882a593Smuzhiyun 		badness = fill_and_eval_dacs(codec, fill_hardwired,
1997*4882a593Smuzhiyun 					     fill_mio_first);
1998*4882a593Smuzhiyun 		if (badness < 0) {
1999*4882a593Smuzhiyun 			kfree(best_cfg);
2000*4882a593Smuzhiyun 			return badness;
2001*4882a593Smuzhiyun 		}
2002*4882a593Smuzhiyun 		debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
2003*4882a593Smuzhiyun 			      cfg->line_out_type, fill_hardwired, fill_mio_first,
2004*4882a593Smuzhiyun 			      badness);
2005*4882a593Smuzhiyun 		debug_show_configs(codec, cfg);
2006*4882a593Smuzhiyun 		if (badness < best_badness) {
2007*4882a593Smuzhiyun 			best_badness = badness;
2008*4882a593Smuzhiyun 			*best_cfg = *cfg;
2009*4882a593Smuzhiyun 			best_wired = fill_hardwired;
2010*4882a593Smuzhiyun 			best_mio = fill_mio_first;
2011*4882a593Smuzhiyun 		}
2012*4882a593Smuzhiyun 		if (!badness)
2013*4882a593Smuzhiyun 			break;
2014*4882a593Smuzhiyun 		fill_mio_first = !fill_mio_first;
2015*4882a593Smuzhiyun 		if (!fill_mio_first)
2016*4882a593Smuzhiyun 			continue;
2017*4882a593Smuzhiyun 		fill_hardwired = !fill_hardwired;
2018*4882a593Smuzhiyun 		if (!fill_hardwired)
2019*4882a593Smuzhiyun 			continue;
2020*4882a593Smuzhiyun 		if (hp_spk_swapped)
2021*4882a593Smuzhiyun 			break;
2022*4882a593Smuzhiyun 		hp_spk_swapped = true;
2023*4882a593Smuzhiyun 		if (cfg->speaker_outs > 0 &&
2024*4882a593Smuzhiyun 		    cfg->line_out_type == AUTO_PIN_HP_OUT) {
2025*4882a593Smuzhiyun 			cfg->hp_outs = cfg->line_outs;
2026*4882a593Smuzhiyun 			memcpy(cfg->hp_pins, cfg->line_out_pins,
2027*4882a593Smuzhiyun 			       sizeof(cfg->hp_pins));
2028*4882a593Smuzhiyun 			cfg->line_outs = cfg->speaker_outs;
2029*4882a593Smuzhiyun 			memcpy(cfg->line_out_pins, cfg->speaker_pins,
2030*4882a593Smuzhiyun 			       sizeof(cfg->speaker_pins));
2031*4882a593Smuzhiyun 			cfg->speaker_outs = 0;
2032*4882a593Smuzhiyun 			memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
2033*4882a593Smuzhiyun 			cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
2034*4882a593Smuzhiyun 			fill_hardwired = true;
2035*4882a593Smuzhiyun 			continue;
2036*4882a593Smuzhiyun 		}
2037*4882a593Smuzhiyun 		if (cfg->hp_outs > 0 &&
2038*4882a593Smuzhiyun 		    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
2039*4882a593Smuzhiyun 			cfg->speaker_outs = cfg->line_outs;
2040*4882a593Smuzhiyun 			memcpy(cfg->speaker_pins, cfg->line_out_pins,
2041*4882a593Smuzhiyun 			       sizeof(cfg->speaker_pins));
2042*4882a593Smuzhiyun 			cfg->line_outs = cfg->hp_outs;
2043*4882a593Smuzhiyun 			memcpy(cfg->line_out_pins, cfg->hp_pins,
2044*4882a593Smuzhiyun 			       sizeof(cfg->hp_pins));
2045*4882a593Smuzhiyun 			cfg->hp_outs = 0;
2046*4882a593Smuzhiyun 			memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
2047*4882a593Smuzhiyun 			cfg->line_out_type = AUTO_PIN_HP_OUT;
2048*4882a593Smuzhiyun 			fill_hardwired = true;
2049*4882a593Smuzhiyun 			continue;
2050*4882a593Smuzhiyun 		}
2051*4882a593Smuzhiyun 		break;
2052*4882a593Smuzhiyun 	}
2053*4882a593Smuzhiyun 
2054*4882a593Smuzhiyun 	if (badness) {
2055*4882a593Smuzhiyun 		debug_badness("==> restoring best_cfg\n");
2056*4882a593Smuzhiyun 		*cfg = *best_cfg;
2057*4882a593Smuzhiyun 		fill_and_eval_dacs(codec, best_wired, best_mio);
2058*4882a593Smuzhiyun 	}
2059*4882a593Smuzhiyun 	debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
2060*4882a593Smuzhiyun 		      cfg->line_out_type, best_wired, best_mio);
2061*4882a593Smuzhiyun 	debug_show_configs(codec, cfg);
2062*4882a593Smuzhiyun 
2063*4882a593Smuzhiyun 	if (cfg->line_out_pins[0]) {
2064*4882a593Smuzhiyun 		struct nid_path *path;
2065*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]);
2066*4882a593Smuzhiyun 		if (path)
2067*4882a593Smuzhiyun 			spec->vmaster_nid = look_for_out_vol_nid(codec, path);
2068*4882a593Smuzhiyun 		if (spec->vmaster_nid) {
2069*4882a593Smuzhiyun 			snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
2070*4882a593Smuzhiyun 						HDA_OUTPUT, spec->vmaster_tlv);
2071*4882a593Smuzhiyun 			if (spec->dac_min_mute)
2072*4882a593Smuzhiyun 				spec->vmaster_tlv[SNDRV_CTL_TLVO_DB_SCALE_MUTE_AND_STEP] |= TLV_DB_SCALE_MUTE;
2073*4882a593Smuzhiyun 		}
2074*4882a593Smuzhiyun 	}
2075*4882a593Smuzhiyun 
2076*4882a593Smuzhiyun 	/* set initial pinctl targets */
2077*4882a593Smuzhiyun 	if (spec->prefer_hp_amp || cfg->line_out_type == AUTO_PIN_HP_OUT)
2078*4882a593Smuzhiyun 		val = PIN_HP;
2079*4882a593Smuzhiyun 	else
2080*4882a593Smuzhiyun 		val = PIN_OUT;
2081*4882a593Smuzhiyun 	set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins, val);
2082*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2083*4882a593Smuzhiyun 		set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
2084*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
2085*4882a593Smuzhiyun 		val = spec->prefer_hp_amp ? PIN_HP : PIN_OUT;
2086*4882a593Smuzhiyun 		set_pin_targets(codec, cfg->speaker_outs,
2087*4882a593Smuzhiyun 				cfg->speaker_pins, val);
2088*4882a593Smuzhiyun 	}
2089*4882a593Smuzhiyun 
2090*4882a593Smuzhiyun 	/* clear indep_hp flag if not available */
2091*4882a593Smuzhiyun 	if (spec->indep_hp && !indep_hp_possible(codec))
2092*4882a593Smuzhiyun 		spec->indep_hp = 0;
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun 	kfree(best_cfg);
2095*4882a593Smuzhiyun 	return 0;
2096*4882a593Smuzhiyun }
2097*4882a593Smuzhiyun 
2098*4882a593Smuzhiyun /* add playback controls from the parsed DAC table */
create_multi_out_ctls(struct hda_codec * codec,const struct auto_pin_cfg * cfg)2099*4882a593Smuzhiyun static int create_multi_out_ctls(struct hda_codec *codec,
2100*4882a593Smuzhiyun 				 const struct auto_pin_cfg *cfg)
2101*4882a593Smuzhiyun {
2102*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2103*4882a593Smuzhiyun 	int i, err, noutputs;
2104*4882a593Smuzhiyun 
2105*4882a593Smuzhiyun 	noutputs = cfg->line_outs;
2106*4882a593Smuzhiyun 	if (spec->multi_ios > 0 && cfg->line_outs < 3)
2107*4882a593Smuzhiyun 		noutputs += spec->multi_ios;
2108*4882a593Smuzhiyun 
2109*4882a593Smuzhiyun 	for (i = 0; i < noutputs; i++) {
2110*4882a593Smuzhiyun 		const char *name;
2111*4882a593Smuzhiyun 		int index;
2112*4882a593Smuzhiyun 		struct nid_path *path;
2113*4882a593Smuzhiyun 
2114*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
2115*4882a593Smuzhiyun 		if (!path)
2116*4882a593Smuzhiyun 			continue;
2117*4882a593Smuzhiyun 
2118*4882a593Smuzhiyun 		name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL);
2119*4882a593Smuzhiyun 		if (!name || !strcmp(name, "CLFE")) {
2120*4882a593Smuzhiyun 			/* Center/LFE */
2121*4882a593Smuzhiyun 			err = add_vol_ctl(codec, "Center", 0, 1, path);
2122*4882a593Smuzhiyun 			if (err < 0)
2123*4882a593Smuzhiyun 				return err;
2124*4882a593Smuzhiyun 			err = add_vol_ctl(codec, "LFE", 0, 2, path);
2125*4882a593Smuzhiyun 			if (err < 0)
2126*4882a593Smuzhiyun 				return err;
2127*4882a593Smuzhiyun 		} else {
2128*4882a593Smuzhiyun 			err = add_stereo_vol(codec, name, index, path);
2129*4882a593Smuzhiyun 			if (err < 0)
2130*4882a593Smuzhiyun 				return err;
2131*4882a593Smuzhiyun 		}
2132*4882a593Smuzhiyun 
2133*4882a593Smuzhiyun 		name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL);
2134*4882a593Smuzhiyun 		if (!name || !strcmp(name, "CLFE")) {
2135*4882a593Smuzhiyun 			err = add_sw_ctl(codec, "Center", 0, 1, path);
2136*4882a593Smuzhiyun 			if (err < 0)
2137*4882a593Smuzhiyun 				return err;
2138*4882a593Smuzhiyun 			err = add_sw_ctl(codec, "LFE", 0, 2, path);
2139*4882a593Smuzhiyun 			if (err < 0)
2140*4882a593Smuzhiyun 				return err;
2141*4882a593Smuzhiyun 		} else {
2142*4882a593Smuzhiyun 			err = add_stereo_sw(codec, name, index, path);
2143*4882a593Smuzhiyun 			if (err < 0)
2144*4882a593Smuzhiyun 				return err;
2145*4882a593Smuzhiyun 		}
2146*4882a593Smuzhiyun 	}
2147*4882a593Smuzhiyun 	return 0;
2148*4882a593Smuzhiyun }
2149*4882a593Smuzhiyun 
create_extra_out(struct hda_codec * codec,int path_idx,const char * pfx,int cidx)2150*4882a593Smuzhiyun static int create_extra_out(struct hda_codec *codec, int path_idx,
2151*4882a593Smuzhiyun 			    const char *pfx, int cidx)
2152*4882a593Smuzhiyun {
2153*4882a593Smuzhiyun 	struct nid_path *path;
2154*4882a593Smuzhiyun 	int err;
2155*4882a593Smuzhiyun 
2156*4882a593Smuzhiyun 	path = snd_hda_get_path_from_idx(codec, path_idx);
2157*4882a593Smuzhiyun 	if (!path)
2158*4882a593Smuzhiyun 		return 0;
2159*4882a593Smuzhiyun 	err = add_stereo_vol(codec, pfx, cidx, path);
2160*4882a593Smuzhiyun 	if (err < 0)
2161*4882a593Smuzhiyun 		return err;
2162*4882a593Smuzhiyun 	err = add_stereo_sw(codec, pfx, cidx, path);
2163*4882a593Smuzhiyun 	if (err < 0)
2164*4882a593Smuzhiyun 		return err;
2165*4882a593Smuzhiyun 	return 0;
2166*4882a593Smuzhiyun }
2167*4882a593Smuzhiyun 
2168*4882a593Smuzhiyun /* add playback controls for speaker and HP outputs */
create_extra_outs(struct hda_codec * codec,int num_pins,const int * paths,const char * pfx)2169*4882a593Smuzhiyun static int create_extra_outs(struct hda_codec *codec, int num_pins,
2170*4882a593Smuzhiyun 			     const int *paths, const char *pfx)
2171*4882a593Smuzhiyun {
2172*4882a593Smuzhiyun 	int i;
2173*4882a593Smuzhiyun 
2174*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++) {
2175*4882a593Smuzhiyun 		const char *name;
2176*4882a593Smuzhiyun 		char tmp[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2177*4882a593Smuzhiyun 		int err, idx = 0;
2178*4882a593Smuzhiyun 
2179*4882a593Smuzhiyun 		if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker"))
2180*4882a593Smuzhiyun 			name = "Bass Speaker";
2181*4882a593Smuzhiyun 		else if (num_pins >= 3) {
2182*4882a593Smuzhiyun 			snprintf(tmp, sizeof(tmp), "%s %s",
2183*4882a593Smuzhiyun 				 pfx, channel_name[i]);
2184*4882a593Smuzhiyun 			name = tmp;
2185*4882a593Smuzhiyun 		} else {
2186*4882a593Smuzhiyun 			name = pfx;
2187*4882a593Smuzhiyun 			idx = i;
2188*4882a593Smuzhiyun 		}
2189*4882a593Smuzhiyun 		err = create_extra_out(codec, paths[i], name, idx);
2190*4882a593Smuzhiyun 		if (err < 0)
2191*4882a593Smuzhiyun 			return err;
2192*4882a593Smuzhiyun 	}
2193*4882a593Smuzhiyun 	return 0;
2194*4882a593Smuzhiyun }
2195*4882a593Smuzhiyun 
create_hp_out_ctls(struct hda_codec * codec)2196*4882a593Smuzhiyun static int create_hp_out_ctls(struct hda_codec *codec)
2197*4882a593Smuzhiyun {
2198*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2199*4882a593Smuzhiyun 	return create_extra_outs(codec, spec->autocfg.hp_outs,
2200*4882a593Smuzhiyun 				 spec->hp_paths,
2201*4882a593Smuzhiyun 				 "Headphone");
2202*4882a593Smuzhiyun }
2203*4882a593Smuzhiyun 
create_speaker_out_ctls(struct hda_codec * codec)2204*4882a593Smuzhiyun static int create_speaker_out_ctls(struct hda_codec *codec)
2205*4882a593Smuzhiyun {
2206*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2207*4882a593Smuzhiyun 	return create_extra_outs(codec, spec->autocfg.speaker_outs,
2208*4882a593Smuzhiyun 				 spec->speaker_paths,
2209*4882a593Smuzhiyun 				 "Speaker");
2210*4882a593Smuzhiyun }
2211*4882a593Smuzhiyun 
2212*4882a593Smuzhiyun /*
2213*4882a593Smuzhiyun  * independent HP controls
2214*4882a593Smuzhiyun  */
2215*4882a593Smuzhiyun 
2216*4882a593Smuzhiyun static void call_hp_automute(struct hda_codec *codec,
2217*4882a593Smuzhiyun 			     struct hda_jack_callback *jack);
indep_hp_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2218*4882a593Smuzhiyun static int indep_hp_info(struct snd_kcontrol *kcontrol,
2219*4882a593Smuzhiyun 			 struct snd_ctl_elem_info *uinfo)
2220*4882a593Smuzhiyun {
2221*4882a593Smuzhiyun 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
2222*4882a593Smuzhiyun }
2223*4882a593Smuzhiyun 
indep_hp_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2224*4882a593Smuzhiyun static int indep_hp_get(struct snd_kcontrol *kcontrol,
2225*4882a593Smuzhiyun 			struct snd_ctl_elem_value *ucontrol)
2226*4882a593Smuzhiyun {
2227*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2228*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2229*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = spec->indep_hp_enabled;
2230*4882a593Smuzhiyun 	return 0;
2231*4882a593Smuzhiyun }
2232*4882a593Smuzhiyun 
2233*4882a593Smuzhiyun static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2234*4882a593Smuzhiyun 			       int nomix_path_idx, int mix_path_idx,
2235*4882a593Smuzhiyun 			       int out_type);
2236*4882a593Smuzhiyun 
indep_hp_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2237*4882a593Smuzhiyun static int indep_hp_put(struct snd_kcontrol *kcontrol,
2238*4882a593Smuzhiyun 			struct snd_ctl_elem_value *ucontrol)
2239*4882a593Smuzhiyun {
2240*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2241*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2242*4882a593Smuzhiyun 	unsigned int select = ucontrol->value.enumerated.item[0];
2243*4882a593Smuzhiyun 	int ret = 0;
2244*4882a593Smuzhiyun 
2245*4882a593Smuzhiyun 	mutex_lock(&spec->pcm_mutex);
2246*4882a593Smuzhiyun 	if (spec->active_streams) {
2247*4882a593Smuzhiyun 		ret = -EBUSY;
2248*4882a593Smuzhiyun 		goto unlock;
2249*4882a593Smuzhiyun 	}
2250*4882a593Smuzhiyun 
2251*4882a593Smuzhiyun 	if (spec->indep_hp_enabled != select) {
2252*4882a593Smuzhiyun 		hda_nid_t *dacp;
2253*4882a593Smuzhiyun 		if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2254*4882a593Smuzhiyun 			dacp = &spec->private_dac_nids[0];
2255*4882a593Smuzhiyun 		else
2256*4882a593Smuzhiyun 			dacp = &spec->multiout.hp_out_nid[0];
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun 		/* update HP aamix paths in case it conflicts with indep HP */
2259*4882a593Smuzhiyun 		if (spec->have_aamix_ctl) {
2260*4882a593Smuzhiyun 			if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2261*4882a593Smuzhiyun 				update_aamix_paths(codec, spec->aamix_mode,
2262*4882a593Smuzhiyun 						   spec->out_paths[0],
2263*4882a593Smuzhiyun 						   spec->aamix_out_paths[0],
2264*4882a593Smuzhiyun 						   spec->autocfg.line_out_type);
2265*4882a593Smuzhiyun 			else
2266*4882a593Smuzhiyun 				update_aamix_paths(codec, spec->aamix_mode,
2267*4882a593Smuzhiyun 						   spec->hp_paths[0],
2268*4882a593Smuzhiyun 						   spec->aamix_out_paths[1],
2269*4882a593Smuzhiyun 						   AUTO_PIN_HP_OUT);
2270*4882a593Smuzhiyun 		}
2271*4882a593Smuzhiyun 
2272*4882a593Smuzhiyun 		spec->indep_hp_enabled = select;
2273*4882a593Smuzhiyun 		if (spec->indep_hp_enabled)
2274*4882a593Smuzhiyun 			*dacp = 0;
2275*4882a593Smuzhiyun 		else
2276*4882a593Smuzhiyun 			*dacp = spec->alt_dac_nid;
2277*4882a593Smuzhiyun 
2278*4882a593Smuzhiyun 		call_hp_automute(codec, NULL);
2279*4882a593Smuzhiyun 		ret = 1;
2280*4882a593Smuzhiyun 	}
2281*4882a593Smuzhiyun  unlock:
2282*4882a593Smuzhiyun 	mutex_unlock(&spec->pcm_mutex);
2283*4882a593Smuzhiyun 	return ret;
2284*4882a593Smuzhiyun }
2285*4882a593Smuzhiyun 
2286*4882a593Smuzhiyun static const struct snd_kcontrol_new indep_hp_ctl = {
2287*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2288*4882a593Smuzhiyun 	.name = "Independent HP",
2289*4882a593Smuzhiyun 	.info = indep_hp_info,
2290*4882a593Smuzhiyun 	.get = indep_hp_get,
2291*4882a593Smuzhiyun 	.put = indep_hp_put,
2292*4882a593Smuzhiyun };
2293*4882a593Smuzhiyun 
2294*4882a593Smuzhiyun 
create_indep_hp_ctls(struct hda_codec * codec)2295*4882a593Smuzhiyun static int create_indep_hp_ctls(struct hda_codec *codec)
2296*4882a593Smuzhiyun {
2297*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2298*4882a593Smuzhiyun 	hda_nid_t dac;
2299*4882a593Smuzhiyun 
2300*4882a593Smuzhiyun 	if (!spec->indep_hp)
2301*4882a593Smuzhiyun 		return 0;
2302*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
2303*4882a593Smuzhiyun 		dac = spec->multiout.dac_nids[0];
2304*4882a593Smuzhiyun 	else
2305*4882a593Smuzhiyun 		dac = spec->multiout.hp_out_nid[0];
2306*4882a593Smuzhiyun 	if (!dac) {
2307*4882a593Smuzhiyun 		spec->indep_hp = 0;
2308*4882a593Smuzhiyun 		return 0;
2309*4882a593Smuzhiyun 	}
2310*4882a593Smuzhiyun 
2311*4882a593Smuzhiyun 	spec->indep_hp_enabled = false;
2312*4882a593Smuzhiyun 	spec->alt_dac_nid = dac;
2313*4882a593Smuzhiyun 	if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
2314*4882a593Smuzhiyun 		return -ENOMEM;
2315*4882a593Smuzhiyun 	return 0;
2316*4882a593Smuzhiyun }
2317*4882a593Smuzhiyun 
2318*4882a593Smuzhiyun /*
2319*4882a593Smuzhiyun  * channel mode enum control
2320*4882a593Smuzhiyun  */
2321*4882a593Smuzhiyun 
ch_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2322*4882a593Smuzhiyun static int ch_mode_info(struct snd_kcontrol *kcontrol,
2323*4882a593Smuzhiyun 			struct snd_ctl_elem_info *uinfo)
2324*4882a593Smuzhiyun {
2325*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2326*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2327*4882a593Smuzhiyun 	int chs;
2328*4882a593Smuzhiyun 
2329*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2330*4882a593Smuzhiyun 	uinfo->count = 1;
2331*4882a593Smuzhiyun 	uinfo->value.enumerated.items = spec->multi_ios + 1;
2332*4882a593Smuzhiyun 	if (uinfo->value.enumerated.item > spec->multi_ios)
2333*4882a593Smuzhiyun 		uinfo->value.enumerated.item = spec->multi_ios;
2334*4882a593Smuzhiyun 	chs = uinfo->value.enumerated.item * 2 + spec->min_channel_count;
2335*4882a593Smuzhiyun 	sprintf(uinfo->value.enumerated.name, "%dch", chs);
2336*4882a593Smuzhiyun 	return 0;
2337*4882a593Smuzhiyun }
2338*4882a593Smuzhiyun 
ch_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2339*4882a593Smuzhiyun static int ch_mode_get(struct snd_kcontrol *kcontrol,
2340*4882a593Smuzhiyun 		       struct snd_ctl_elem_value *ucontrol)
2341*4882a593Smuzhiyun {
2342*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2343*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2344*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] =
2345*4882a593Smuzhiyun 		(spec->ext_channel_count - spec->min_channel_count) / 2;
2346*4882a593Smuzhiyun 	return 0;
2347*4882a593Smuzhiyun }
2348*4882a593Smuzhiyun 
2349*4882a593Smuzhiyun static inline struct nid_path *
get_multiio_path(struct hda_codec * codec,int idx)2350*4882a593Smuzhiyun get_multiio_path(struct hda_codec *codec, int idx)
2351*4882a593Smuzhiyun {
2352*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2353*4882a593Smuzhiyun 	return snd_hda_get_path_from_idx(codec,
2354*4882a593Smuzhiyun 		spec->out_paths[spec->autocfg.line_outs + idx]);
2355*4882a593Smuzhiyun }
2356*4882a593Smuzhiyun 
2357*4882a593Smuzhiyun static void update_automute_all(struct hda_codec *codec);
2358*4882a593Smuzhiyun 
2359*4882a593Smuzhiyun /* Default value to be passed as aamix argument for snd_hda_activate_path();
2360*4882a593Smuzhiyun  * used for output paths
2361*4882a593Smuzhiyun  */
aamix_default(struct hda_gen_spec * spec)2362*4882a593Smuzhiyun static bool aamix_default(struct hda_gen_spec *spec)
2363*4882a593Smuzhiyun {
2364*4882a593Smuzhiyun 	return !spec->have_aamix_ctl || spec->aamix_mode;
2365*4882a593Smuzhiyun }
2366*4882a593Smuzhiyun 
set_multi_io(struct hda_codec * codec,int idx,bool output)2367*4882a593Smuzhiyun static int set_multi_io(struct hda_codec *codec, int idx, bool output)
2368*4882a593Smuzhiyun {
2369*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2370*4882a593Smuzhiyun 	hda_nid_t nid = spec->multi_io[idx].pin;
2371*4882a593Smuzhiyun 	struct nid_path *path;
2372*4882a593Smuzhiyun 
2373*4882a593Smuzhiyun 	path = get_multiio_path(codec, idx);
2374*4882a593Smuzhiyun 	if (!path)
2375*4882a593Smuzhiyun 		return -EINVAL;
2376*4882a593Smuzhiyun 
2377*4882a593Smuzhiyun 	if (path->active == output)
2378*4882a593Smuzhiyun 		return 0;
2379*4882a593Smuzhiyun 
2380*4882a593Smuzhiyun 	if (output) {
2381*4882a593Smuzhiyun 		set_pin_target(codec, nid, PIN_OUT, true);
2382*4882a593Smuzhiyun 		snd_hda_activate_path(codec, path, true, aamix_default(spec));
2383*4882a593Smuzhiyun 		set_pin_eapd(codec, nid, true);
2384*4882a593Smuzhiyun 	} else {
2385*4882a593Smuzhiyun 		set_pin_eapd(codec, nid, false);
2386*4882a593Smuzhiyun 		snd_hda_activate_path(codec, path, false, aamix_default(spec));
2387*4882a593Smuzhiyun 		set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
2388*4882a593Smuzhiyun 		path_power_down_sync(codec, path);
2389*4882a593Smuzhiyun 	}
2390*4882a593Smuzhiyun 
2391*4882a593Smuzhiyun 	/* update jack retasking in case it modifies any of them */
2392*4882a593Smuzhiyun 	update_automute_all(codec);
2393*4882a593Smuzhiyun 
2394*4882a593Smuzhiyun 	return 0;
2395*4882a593Smuzhiyun }
2396*4882a593Smuzhiyun 
ch_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2397*4882a593Smuzhiyun static int ch_mode_put(struct snd_kcontrol *kcontrol,
2398*4882a593Smuzhiyun 		       struct snd_ctl_elem_value *ucontrol)
2399*4882a593Smuzhiyun {
2400*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2401*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2402*4882a593Smuzhiyun 	int i, ch;
2403*4882a593Smuzhiyun 
2404*4882a593Smuzhiyun 	ch = ucontrol->value.enumerated.item[0];
2405*4882a593Smuzhiyun 	if (ch < 0 || ch > spec->multi_ios)
2406*4882a593Smuzhiyun 		return -EINVAL;
2407*4882a593Smuzhiyun 	if (ch == (spec->ext_channel_count - spec->min_channel_count) / 2)
2408*4882a593Smuzhiyun 		return 0;
2409*4882a593Smuzhiyun 	spec->ext_channel_count = ch * 2 + spec->min_channel_count;
2410*4882a593Smuzhiyun 	for (i = 0; i < spec->multi_ios; i++)
2411*4882a593Smuzhiyun 		set_multi_io(codec, i, i < ch);
2412*4882a593Smuzhiyun 	spec->multiout.max_channels = max(spec->ext_channel_count,
2413*4882a593Smuzhiyun 					  spec->const_channel_count);
2414*4882a593Smuzhiyun 	if (spec->need_dac_fix)
2415*4882a593Smuzhiyun 		spec->multiout.num_dacs = spec->multiout.max_channels / 2;
2416*4882a593Smuzhiyun 	return 1;
2417*4882a593Smuzhiyun }
2418*4882a593Smuzhiyun 
2419*4882a593Smuzhiyun static const struct snd_kcontrol_new channel_mode_enum = {
2420*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2421*4882a593Smuzhiyun 	.name = "Channel Mode",
2422*4882a593Smuzhiyun 	.info = ch_mode_info,
2423*4882a593Smuzhiyun 	.get = ch_mode_get,
2424*4882a593Smuzhiyun 	.put = ch_mode_put,
2425*4882a593Smuzhiyun };
2426*4882a593Smuzhiyun 
create_multi_channel_mode(struct hda_codec * codec)2427*4882a593Smuzhiyun static int create_multi_channel_mode(struct hda_codec *codec)
2428*4882a593Smuzhiyun {
2429*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2430*4882a593Smuzhiyun 
2431*4882a593Smuzhiyun 	if (spec->multi_ios > 0) {
2432*4882a593Smuzhiyun 		if (!snd_hda_gen_add_kctl(spec, NULL, &channel_mode_enum))
2433*4882a593Smuzhiyun 			return -ENOMEM;
2434*4882a593Smuzhiyun 	}
2435*4882a593Smuzhiyun 	return 0;
2436*4882a593Smuzhiyun }
2437*4882a593Smuzhiyun 
2438*4882a593Smuzhiyun /*
2439*4882a593Smuzhiyun  * aamix loopback enable/disable switch
2440*4882a593Smuzhiyun  */
2441*4882a593Smuzhiyun 
2442*4882a593Smuzhiyun #define loopback_mixing_info	indep_hp_info
2443*4882a593Smuzhiyun 
loopback_mixing_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2444*4882a593Smuzhiyun static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2445*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
2446*4882a593Smuzhiyun {
2447*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2448*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2449*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = spec->aamix_mode;
2450*4882a593Smuzhiyun 	return 0;
2451*4882a593Smuzhiyun }
2452*4882a593Smuzhiyun 
update_aamix_paths(struct hda_codec * codec,bool do_mix,int nomix_path_idx,int mix_path_idx,int out_type)2453*4882a593Smuzhiyun static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2454*4882a593Smuzhiyun 			       int nomix_path_idx, int mix_path_idx,
2455*4882a593Smuzhiyun 			       int out_type)
2456*4882a593Smuzhiyun {
2457*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2458*4882a593Smuzhiyun 	struct nid_path *nomix_path, *mix_path;
2459*4882a593Smuzhiyun 
2460*4882a593Smuzhiyun 	nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2461*4882a593Smuzhiyun 	mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2462*4882a593Smuzhiyun 	if (!nomix_path || !mix_path)
2463*4882a593Smuzhiyun 		return;
2464*4882a593Smuzhiyun 
2465*4882a593Smuzhiyun 	/* if HP aamix path is driven from a different DAC and the
2466*4882a593Smuzhiyun 	 * independent HP mode is ON, can't turn on aamix path
2467*4882a593Smuzhiyun 	 */
2468*4882a593Smuzhiyun 	if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2469*4882a593Smuzhiyun 	    mix_path->path[0] != spec->alt_dac_nid)
2470*4882a593Smuzhiyun 		do_mix = false;
2471*4882a593Smuzhiyun 
2472*4882a593Smuzhiyun 	if (do_mix) {
2473*4882a593Smuzhiyun 		snd_hda_activate_path(codec, nomix_path, false, true);
2474*4882a593Smuzhiyun 		snd_hda_activate_path(codec, mix_path, true, true);
2475*4882a593Smuzhiyun 		path_power_down_sync(codec, nomix_path);
2476*4882a593Smuzhiyun 	} else {
2477*4882a593Smuzhiyun 		snd_hda_activate_path(codec, mix_path, false, false);
2478*4882a593Smuzhiyun 		snd_hda_activate_path(codec, nomix_path, true, false);
2479*4882a593Smuzhiyun 		path_power_down_sync(codec, mix_path);
2480*4882a593Smuzhiyun 	}
2481*4882a593Smuzhiyun }
2482*4882a593Smuzhiyun 
2483*4882a593Smuzhiyun /* re-initialize the output paths; only called from loopback_mixing_put() */
update_output_paths(struct hda_codec * codec,int num_outs,const int * paths)2484*4882a593Smuzhiyun static void update_output_paths(struct hda_codec *codec, int num_outs,
2485*4882a593Smuzhiyun 				const int *paths)
2486*4882a593Smuzhiyun {
2487*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2488*4882a593Smuzhiyun 	struct nid_path *path;
2489*4882a593Smuzhiyun 	int i;
2490*4882a593Smuzhiyun 
2491*4882a593Smuzhiyun 	for (i = 0; i < num_outs; i++) {
2492*4882a593Smuzhiyun 		path = snd_hda_get_path_from_idx(codec, paths[i]);
2493*4882a593Smuzhiyun 		if (path)
2494*4882a593Smuzhiyun 			snd_hda_activate_path(codec, path, path->active,
2495*4882a593Smuzhiyun 					      spec->aamix_mode);
2496*4882a593Smuzhiyun 	}
2497*4882a593Smuzhiyun }
2498*4882a593Smuzhiyun 
loopback_mixing_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2499*4882a593Smuzhiyun static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2500*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
2501*4882a593Smuzhiyun {
2502*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2503*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2504*4882a593Smuzhiyun 	const struct auto_pin_cfg *cfg = &spec->autocfg;
2505*4882a593Smuzhiyun 	unsigned int val = ucontrol->value.enumerated.item[0];
2506*4882a593Smuzhiyun 
2507*4882a593Smuzhiyun 	if (val == spec->aamix_mode)
2508*4882a593Smuzhiyun 		return 0;
2509*4882a593Smuzhiyun 	spec->aamix_mode = val;
2510*4882a593Smuzhiyun 	if (has_aamix_out_paths(spec)) {
2511*4882a593Smuzhiyun 		update_aamix_paths(codec, val, spec->out_paths[0],
2512*4882a593Smuzhiyun 				   spec->aamix_out_paths[0],
2513*4882a593Smuzhiyun 				   cfg->line_out_type);
2514*4882a593Smuzhiyun 		update_aamix_paths(codec, val, spec->hp_paths[0],
2515*4882a593Smuzhiyun 				   spec->aamix_out_paths[1],
2516*4882a593Smuzhiyun 				   AUTO_PIN_HP_OUT);
2517*4882a593Smuzhiyun 		update_aamix_paths(codec, val, spec->speaker_paths[0],
2518*4882a593Smuzhiyun 				   spec->aamix_out_paths[2],
2519*4882a593Smuzhiyun 				   AUTO_PIN_SPEAKER_OUT);
2520*4882a593Smuzhiyun 	} else {
2521*4882a593Smuzhiyun 		update_output_paths(codec, cfg->line_outs, spec->out_paths);
2522*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
2523*4882a593Smuzhiyun 			update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
2524*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
2525*4882a593Smuzhiyun 			update_output_paths(codec, cfg->speaker_outs,
2526*4882a593Smuzhiyun 					    spec->speaker_paths);
2527*4882a593Smuzhiyun 	}
2528*4882a593Smuzhiyun 	return 1;
2529*4882a593Smuzhiyun }
2530*4882a593Smuzhiyun 
2531*4882a593Smuzhiyun static const struct snd_kcontrol_new loopback_mixing_enum = {
2532*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2533*4882a593Smuzhiyun 	.name = "Loopback Mixing",
2534*4882a593Smuzhiyun 	.info = loopback_mixing_info,
2535*4882a593Smuzhiyun 	.get = loopback_mixing_get,
2536*4882a593Smuzhiyun 	.put = loopback_mixing_put,
2537*4882a593Smuzhiyun };
2538*4882a593Smuzhiyun 
create_loopback_mixing_ctl(struct hda_codec * codec)2539*4882a593Smuzhiyun static int create_loopback_mixing_ctl(struct hda_codec *codec)
2540*4882a593Smuzhiyun {
2541*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2542*4882a593Smuzhiyun 
2543*4882a593Smuzhiyun 	if (!spec->mixer_nid)
2544*4882a593Smuzhiyun 		return 0;
2545*4882a593Smuzhiyun 	if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2546*4882a593Smuzhiyun 		return -ENOMEM;
2547*4882a593Smuzhiyun 	spec->have_aamix_ctl = 1;
2548*4882a593Smuzhiyun 	return 0;
2549*4882a593Smuzhiyun }
2550*4882a593Smuzhiyun 
2551*4882a593Smuzhiyun /*
2552*4882a593Smuzhiyun  * shared headphone/mic handling
2553*4882a593Smuzhiyun  */
2554*4882a593Smuzhiyun 
2555*4882a593Smuzhiyun static void call_update_outputs(struct hda_codec *codec);
2556*4882a593Smuzhiyun 
2557*4882a593Smuzhiyun /* for shared I/O, change the pin-control accordingly */
update_hp_mic(struct hda_codec * codec,int adc_mux,bool force)2558*4882a593Smuzhiyun static void update_hp_mic(struct hda_codec *codec, int adc_mux, bool force)
2559*4882a593Smuzhiyun {
2560*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2561*4882a593Smuzhiyun 	bool as_mic;
2562*4882a593Smuzhiyun 	unsigned int val;
2563*4882a593Smuzhiyun 	hda_nid_t pin;
2564*4882a593Smuzhiyun 
2565*4882a593Smuzhiyun 	pin = spec->hp_mic_pin;
2566*4882a593Smuzhiyun 	as_mic = spec->cur_mux[adc_mux] == spec->hp_mic_mux_idx;
2567*4882a593Smuzhiyun 
2568*4882a593Smuzhiyun 	if (!force) {
2569*4882a593Smuzhiyun 		val = snd_hda_codec_get_pin_target(codec, pin);
2570*4882a593Smuzhiyun 		if (as_mic) {
2571*4882a593Smuzhiyun 			if (val & PIN_IN)
2572*4882a593Smuzhiyun 				return;
2573*4882a593Smuzhiyun 		} else {
2574*4882a593Smuzhiyun 			if (val & PIN_OUT)
2575*4882a593Smuzhiyun 				return;
2576*4882a593Smuzhiyun 		}
2577*4882a593Smuzhiyun 	}
2578*4882a593Smuzhiyun 
2579*4882a593Smuzhiyun 	val = snd_hda_get_default_vref(codec, pin);
2580*4882a593Smuzhiyun 	/* if the HP pin doesn't support VREF and the codec driver gives an
2581*4882a593Smuzhiyun 	 * alternative pin, set up the VREF on that pin instead
2582*4882a593Smuzhiyun 	 */
2583*4882a593Smuzhiyun 	if (val == AC_PINCTL_VREF_HIZ && spec->shared_mic_vref_pin) {
2584*4882a593Smuzhiyun 		const hda_nid_t vref_pin = spec->shared_mic_vref_pin;
2585*4882a593Smuzhiyun 		unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin);
2586*4882a593Smuzhiyun 		if (vref_val != AC_PINCTL_VREF_HIZ)
2587*4882a593Smuzhiyun 			snd_hda_set_pin_ctl_cache(codec, vref_pin,
2588*4882a593Smuzhiyun 						  PIN_IN | (as_mic ? vref_val : 0));
2589*4882a593Smuzhiyun 	}
2590*4882a593Smuzhiyun 
2591*4882a593Smuzhiyun 	if (!spec->hp_mic_jack_modes) {
2592*4882a593Smuzhiyun 		if (as_mic)
2593*4882a593Smuzhiyun 			val |= PIN_IN;
2594*4882a593Smuzhiyun 		else
2595*4882a593Smuzhiyun 			val = PIN_HP;
2596*4882a593Smuzhiyun 		set_pin_target(codec, pin, val, true);
2597*4882a593Smuzhiyun 		call_hp_automute(codec, NULL);
2598*4882a593Smuzhiyun 	}
2599*4882a593Smuzhiyun }
2600*4882a593Smuzhiyun 
2601*4882a593Smuzhiyun /* create a shared input with the headphone out */
create_hp_mic(struct hda_codec * codec)2602*4882a593Smuzhiyun static int create_hp_mic(struct hda_codec *codec)
2603*4882a593Smuzhiyun {
2604*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2605*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
2606*4882a593Smuzhiyun 	unsigned int defcfg;
2607*4882a593Smuzhiyun 	hda_nid_t nid;
2608*4882a593Smuzhiyun 
2609*4882a593Smuzhiyun 	if (!spec->hp_mic) {
2610*4882a593Smuzhiyun 		if (spec->suppress_hp_mic_detect)
2611*4882a593Smuzhiyun 			return 0;
2612*4882a593Smuzhiyun 		/* automatic detection: only if no input or a single internal
2613*4882a593Smuzhiyun 		 * input pin is found, try to detect the shared hp/mic
2614*4882a593Smuzhiyun 		 */
2615*4882a593Smuzhiyun 		if (cfg->num_inputs > 1)
2616*4882a593Smuzhiyun 			return 0;
2617*4882a593Smuzhiyun 		else if (cfg->num_inputs == 1) {
2618*4882a593Smuzhiyun 			defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
2619*4882a593Smuzhiyun 			if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
2620*4882a593Smuzhiyun 				return 0;
2621*4882a593Smuzhiyun 		}
2622*4882a593Smuzhiyun 	}
2623*4882a593Smuzhiyun 
2624*4882a593Smuzhiyun 	spec->hp_mic = 0; /* clear once */
2625*4882a593Smuzhiyun 	if (cfg->num_inputs >= AUTO_CFG_MAX_INS)
2626*4882a593Smuzhiyun 		return 0;
2627*4882a593Smuzhiyun 
2628*4882a593Smuzhiyun 	nid = 0;
2629*4882a593Smuzhiyun 	if (cfg->line_out_type == AUTO_PIN_HP_OUT && cfg->line_outs > 0)
2630*4882a593Smuzhiyun 		nid = cfg->line_out_pins[0];
2631*4882a593Smuzhiyun 	else if (cfg->hp_outs > 0)
2632*4882a593Smuzhiyun 		nid = cfg->hp_pins[0];
2633*4882a593Smuzhiyun 	if (!nid)
2634*4882a593Smuzhiyun 		return 0;
2635*4882a593Smuzhiyun 
2636*4882a593Smuzhiyun 	if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
2637*4882a593Smuzhiyun 		return 0; /* no input */
2638*4882a593Smuzhiyun 
2639*4882a593Smuzhiyun 	cfg->inputs[cfg->num_inputs].pin = nid;
2640*4882a593Smuzhiyun 	cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
2641*4882a593Smuzhiyun 	cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
2642*4882a593Smuzhiyun 	cfg->num_inputs++;
2643*4882a593Smuzhiyun 	spec->hp_mic = 1;
2644*4882a593Smuzhiyun 	spec->hp_mic_pin = nid;
2645*4882a593Smuzhiyun 	/* we can't handle auto-mic together with HP-mic */
2646*4882a593Smuzhiyun 	spec->suppress_auto_mic = 1;
2647*4882a593Smuzhiyun 	codec_dbg(codec, "Enable shared I/O jack on NID 0x%x\n", nid);
2648*4882a593Smuzhiyun 	return 0;
2649*4882a593Smuzhiyun }
2650*4882a593Smuzhiyun 
2651*4882a593Smuzhiyun /*
2652*4882a593Smuzhiyun  * output jack mode
2653*4882a593Smuzhiyun  */
2654*4882a593Smuzhiyun 
2655*4882a593Smuzhiyun static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin);
2656*4882a593Smuzhiyun 
2657*4882a593Smuzhiyun static const char * const out_jack_texts[] = {
2658*4882a593Smuzhiyun 	"Line Out", "Headphone Out",
2659*4882a593Smuzhiyun };
2660*4882a593Smuzhiyun 
out_jack_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2661*4882a593Smuzhiyun static int out_jack_mode_info(struct snd_kcontrol *kcontrol,
2662*4882a593Smuzhiyun 			      struct snd_ctl_elem_info *uinfo)
2663*4882a593Smuzhiyun {
2664*4882a593Smuzhiyun 	return snd_hda_enum_helper_info(kcontrol, uinfo, 2, out_jack_texts);
2665*4882a593Smuzhiyun }
2666*4882a593Smuzhiyun 
out_jack_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2667*4882a593Smuzhiyun static int out_jack_mode_get(struct snd_kcontrol *kcontrol,
2668*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
2669*4882a593Smuzhiyun {
2670*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2671*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2672*4882a593Smuzhiyun 	if (snd_hda_codec_get_pin_target(codec, nid) == PIN_HP)
2673*4882a593Smuzhiyun 		ucontrol->value.enumerated.item[0] = 1;
2674*4882a593Smuzhiyun 	else
2675*4882a593Smuzhiyun 		ucontrol->value.enumerated.item[0] = 0;
2676*4882a593Smuzhiyun 	return 0;
2677*4882a593Smuzhiyun }
2678*4882a593Smuzhiyun 
out_jack_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2679*4882a593Smuzhiyun static int out_jack_mode_put(struct snd_kcontrol *kcontrol,
2680*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
2681*4882a593Smuzhiyun {
2682*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2683*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2684*4882a593Smuzhiyun 	unsigned int val;
2685*4882a593Smuzhiyun 
2686*4882a593Smuzhiyun 	val = ucontrol->value.enumerated.item[0] ? PIN_HP : PIN_OUT;
2687*4882a593Smuzhiyun 	if (snd_hda_codec_get_pin_target(codec, nid) == val)
2688*4882a593Smuzhiyun 		return 0;
2689*4882a593Smuzhiyun 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2690*4882a593Smuzhiyun 	return 1;
2691*4882a593Smuzhiyun }
2692*4882a593Smuzhiyun 
2693*4882a593Smuzhiyun static const struct snd_kcontrol_new out_jack_mode_enum = {
2694*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2695*4882a593Smuzhiyun 	.info = out_jack_mode_info,
2696*4882a593Smuzhiyun 	.get = out_jack_mode_get,
2697*4882a593Smuzhiyun 	.put = out_jack_mode_put,
2698*4882a593Smuzhiyun };
2699*4882a593Smuzhiyun 
find_kctl_name(struct hda_codec * codec,const char * name,int idx)2700*4882a593Smuzhiyun static bool find_kctl_name(struct hda_codec *codec, const char *name, int idx)
2701*4882a593Smuzhiyun {
2702*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2703*4882a593Smuzhiyun 	const struct snd_kcontrol_new *kctl;
2704*4882a593Smuzhiyun 	int i;
2705*4882a593Smuzhiyun 
2706*4882a593Smuzhiyun 	snd_array_for_each(&spec->kctls, i, kctl) {
2707*4882a593Smuzhiyun 		if (!strcmp(kctl->name, name) && kctl->index == idx)
2708*4882a593Smuzhiyun 			return true;
2709*4882a593Smuzhiyun 	}
2710*4882a593Smuzhiyun 	return false;
2711*4882a593Smuzhiyun }
2712*4882a593Smuzhiyun 
get_jack_mode_name(struct hda_codec * codec,hda_nid_t pin,char * name,size_t name_len)2713*4882a593Smuzhiyun static void get_jack_mode_name(struct hda_codec *codec, hda_nid_t pin,
2714*4882a593Smuzhiyun 			       char *name, size_t name_len)
2715*4882a593Smuzhiyun {
2716*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2717*4882a593Smuzhiyun 	int idx = 0;
2718*4882a593Smuzhiyun 
2719*4882a593Smuzhiyun 	snd_hda_get_pin_label(codec, pin, &spec->autocfg, name, name_len, &idx);
2720*4882a593Smuzhiyun 	strlcat(name, " Jack Mode", name_len);
2721*4882a593Smuzhiyun 
2722*4882a593Smuzhiyun 	for (; find_kctl_name(codec, name, idx); idx++)
2723*4882a593Smuzhiyun 		;
2724*4882a593Smuzhiyun }
2725*4882a593Smuzhiyun 
get_out_jack_num_items(struct hda_codec * codec,hda_nid_t pin)2726*4882a593Smuzhiyun static int get_out_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
2727*4882a593Smuzhiyun {
2728*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2729*4882a593Smuzhiyun 	if (spec->add_jack_modes) {
2730*4882a593Smuzhiyun 		unsigned int pincap = snd_hda_query_pin_caps(codec, pin);
2731*4882a593Smuzhiyun 		if ((pincap & AC_PINCAP_OUT) && (pincap & AC_PINCAP_HP_DRV))
2732*4882a593Smuzhiyun 			return 2;
2733*4882a593Smuzhiyun 	}
2734*4882a593Smuzhiyun 	return 1;
2735*4882a593Smuzhiyun }
2736*4882a593Smuzhiyun 
create_out_jack_modes(struct hda_codec * codec,int num_pins,hda_nid_t * pins)2737*4882a593Smuzhiyun static int create_out_jack_modes(struct hda_codec *codec, int num_pins,
2738*4882a593Smuzhiyun 				 hda_nid_t *pins)
2739*4882a593Smuzhiyun {
2740*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2741*4882a593Smuzhiyun 	int i;
2742*4882a593Smuzhiyun 
2743*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++) {
2744*4882a593Smuzhiyun 		hda_nid_t pin = pins[i];
2745*4882a593Smuzhiyun 		if (pin == spec->hp_mic_pin)
2746*4882a593Smuzhiyun 			continue;
2747*4882a593Smuzhiyun 		if (get_out_jack_num_items(codec, pin) > 1) {
2748*4882a593Smuzhiyun 			struct snd_kcontrol_new *knew;
2749*4882a593Smuzhiyun 			char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2750*4882a593Smuzhiyun 			get_jack_mode_name(codec, pin, name, sizeof(name));
2751*4882a593Smuzhiyun 			knew = snd_hda_gen_add_kctl(spec, name,
2752*4882a593Smuzhiyun 						    &out_jack_mode_enum);
2753*4882a593Smuzhiyun 			if (!knew)
2754*4882a593Smuzhiyun 				return -ENOMEM;
2755*4882a593Smuzhiyun 			knew->private_value = pin;
2756*4882a593Smuzhiyun 		}
2757*4882a593Smuzhiyun 	}
2758*4882a593Smuzhiyun 
2759*4882a593Smuzhiyun 	return 0;
2760*4882a593Smuzhiyun }
2761*4882a593Smuzhiyun 
2762*4882a593Smuzhiyun /*
2763*4882a593Smuzhiyun  * input jack mode
2764*4882a593Smuzhiyun  */
2765*4882a593Smuzhiyun 
2766*4882a593Smuzhiyun /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */
2767*4882a593Smuzhiyun #define NUM_VREFS	6
2768*4882a593Smuzhiyun 
2769*4882a593Smuzhiyun static const char * const vref_texts[NUM_VREFS] = {
2770*4882a593Smuzhiyun 	"Line In", "Mic 50pc Bias", "Mic 0V Bias",
2771*4882a593Smuzhiyun 	"", "Mic 80pc Bias", "Mic 100pc Bias"
2772*4882a593Smuzhiyun };
2773*4882a593Smuzhiyun 
get_vref_caps(struct hda_codec * codec,hda_nid_t pin)2774*4882a593Smuzhiyun static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin)
2775*4882a593Smuzhiyun {
2776*4882a593Smuzhiyun 	unsigned int pincap;
2777*4882a593Smuzhiyun 
2778*4882a593Smuzhiyun 	pincap = snd_hda_query_pin_caps(codec, pin);
2779*4882a593Smuzhiyun 	pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT;
2780*4882a593Smuzhiyun 	/* filter out unusual vrefs */
2781*4882a593Smuzhiyun 	pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100);
2782*4882a593Smuzhiyun 	return pincap;
2783*4882a593Smuzhiyun }
2784*4882a593Smuzhiyun 
2785*4882a593Smuzhiyun /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */
get_vref_idx(unsigned int vref_caps,unsigned int item_idx)2786*4882a593Smuzhiyun static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx)
2787*4882a593Smuzhiyun {
2788*4882a593Smuzhiyun 	unsigned int i, n = 0;
2789*4882a593Smuzhiyun 
2790*4882a593Smuzhiyun 	for (i = 0; i < NUM_VREFS; i++) {
2791*4882a593Smuzhiyun 		if (vref_caps & (1 << i)) {
2792*4882a593Smuzhiyun 			if (n == item_idx)
2793*4882a593Smuzhiyun 				return i;
2794*4882a593Smuzhiyun 			n++;
2795*4882a593Smuzhiyun 		}
2796*4882a593Smuzhiyun 	}
2797*4882a593Smuzhiyun 	return 0;
2798*4882a593Smuzhiyun }
2799*4882a593Smuzhiyun 
2800*4882a593Smuzhiyun /* convert back from the vref ctl index to the enum item index */
cvt_from_vref_idx(unsigned int vref_caps,unsigned int idx)2801*4882a593Smuzhiyun static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx)
2802*4882a593Smuzhiyun {
2803*4882a593Smuzhiyun 	unsigned int i, n = 0;
2804*4882a593Smuzhiyun 
2805*4882a593Smuzhiyun 	for (i = 0; i < NUM_VREFS; i++) {
2806*4882a593Smuzhiyun 		if (i == idx)
2807*4882a593Smuzhiyun 			return n;
2808*4882a593Smuzhiyun 		if (vref_caps & (1 << i))
2809*4882a593Smuzhiyun 			n++;
2810*4882a593Smuzhiyun 	}
2811*4882a593Smuzhiyun 	return 0;
2812*4882a593Smuzhiyun }
2813*4882a593Smuzhiyun 
in_jack_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2814*4882a593Smuzhiyun static int in_jack_mode_info(struct snd_kcontrol *kcontrol,
2815*4882a593Smuzhiyun 			     struct snd_ctl_elem_info *uinfo)
2816*4882a593Smuzhiyun {
2817*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2818*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2819*4882a593Smuzhiyun 	unsigned int vref_caps = get_vref_caps(codec, nid);
2820*4882a593Smuzhiyun 
2821*4882a593Smuzhiyun 	snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps),
2822*4882a593Smuzhiyun 				 vref_texts);
2823*4882a593Smuzhiyun 	/* set the right text */
2824*4882a593Smuzhiyun 	strcpy(uinfo->value.enumerated.name,
2825*4882a593Smuzhiyun 	       vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]);
2826*4882a593Smuzhiyun 	return 0;
2827*4882a593Smuzhiyun }
2828*4882a593Smuzhiyun 
in_jack_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2829*4882a593Smuzhiyun static int in_jack_mode_get(struct snd_kcontrol *kcontrol,
2830*4882a593Smuzhiyun 			    struct snd_ctl_elem_value *ucontrol)
2831*4882a593Smuzhiyun {
2832*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2833*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2834*4882a593Smuzhiyun 	unsigned int vref_caps = get_vref_caps(codec, nid);
2835*4882a593Smuzhiyun 	unsigned int idx;
2836*4882a593Smuzhiyun 
2837*4882a593Smuzhiyun 	idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN;
2838*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx);
2839*4882a593Smuzhiyun 	return 0;
2840*4882a593Smuzhiyun }
2841*4882a593Smuzhiyun 
in_jack_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2842*4882a593Smuzhiyun static int in_jack_mode_put(struct snd_kcontrol *kcontrol,
2843*4882a593Smuzhiyun 			    struct snd_ctl_elem_value *ucontrol)
2844*4882a593Smuzhiyun {
2845*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2846*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2847*4882a593Smuzhiyun 	unsigned int vref_caps = get_vref_caps(codec, nid);
2848*4882a593Smuzhiyun 	unsigned int val, idx;
2849*4882a593Smuzhiyun 
2850*4882a593Smuzhiyun 	val = snd_hda_codec_get_pin_target(codec, nid);
2851*4882a593Smuzhiyun 	idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN);
2852*4882a593Smuzhiyun 	if (idx == ucontrol->value.enumerated.item[0])
2853*4882a593Smuzhiyun 		return 0;
2854*4882a593Smuzhiyun 
2855*4882a593Smuzhiyun 	val &= ~AC_PINCTL_VREFEN;
2856*4882a593Smuzhiyun 	val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]);
2857*4882a593Smuzhiyun 	snd_hda_set_pin_ctl_cache(codec, nid, val);
2858*4882a593Smuzhiyun 	return 1;
2859*4882a593Smuzhiyun }
2860*4882a593Smuzhiyun 
2861*4882a593Smuzhiyun static const struct snd_kcontrol_new in_jack_mode_enum = {
2862*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2863*4882a593Smuzhiyun 	.info = in_jack_mode_info,
2864*4882a593Smuzhiyun 	.get = in_jack_mode_get,
2865*4882a593Smuzhiyun 	.put = in_jack_mode_put,
2866*4882a593Smuzhiyun };
2867*4882a593Smuzhiyun 
get_in_jack_num_items(struct hda_codec * codec,hda_nid_t pin)2868*4882a593Smuzhiyun static int get_in_jack_num_items(struct hda_codec *codec, hda_nid_t pin)
2869*4882a593Smuzhiyun {
2870*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2871*4882a593Smuzhiyun 	int nitems = 0;
2872*4882a593Smuzhiyun 	if (spec->add_jack_modes)
2873*4882a593Smuzhiyun 		nitems = hweight32(get_vref_caps(codec, pin));
2874*4882a593Smuzhiyun 	return nitems ? nitems : 1;
2875*4882a593Smuzhiyun }
2876*4882a593Smuzhiyun 
create_in_jack_mode(struct hda_codec * codec,hda_nid_t pin)2877*4882a593Smuzhiyun static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin)
2878*4882a593Smuzhiyun {
2879*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
2880*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew;
2881*4882a593Smuzhiyun 	char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
2882*4882a593Smuzhiyun 	unsigned int defcfg;
2883*4882a593Smuzhiyun 
2884*4882a593Smuzhiyun 	if (pin == spec->hp_mic_pin)
2885*4882a593Smuzhiyun 		return 0; /* already done in create_out_jack_mode() */
2886*4882a593Smuzhiyun 
2887*4882a593Smuzhiyun 	/* no jack mode for fixed pins */
2888*4882a593Smuzhiyun 	defcfg = snd_hda_codec_get_pincfg(codec, pin);
2889*4882a593Smuzhiyun 	if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT)
2890*4882a593Smuzhiyun 		return 0;
2891*4882a593Smuzhiyun 
2892*4882a593Smuzhiyun 	/* no multiple vref caps? */
2893*4882a593Smuzhiyun 	if (get_in_jack_num_items(codec, pin) <= 1)
2894*4882a593Smuzhiyun 		return 0;
2895*4882a593Smuzhiyun 
2896*4882a593Smuzhiyun 	get_jack_mode_name(codec, pin, name, sizeof(name));
2897*4882a593Smuzhiyun 	knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum);
2898*4882a593Smuzhiyun 	if (!knew)
2899*4882a593Smuzhiyun 		return -ENOMEM;
2900*4882a593Smuzhiyun 	knew->private_value = pin;
2901*4882a593Smuzhiyun 	return 0;
2902*4882a593Smuzhiyun }
2903*4882a593Smuzhiyun 
2904*4882a593Smuzhiyun /*
2905*4882a593Smuzhiyun  * HP/mic shared jack mode
2906*4882a593Smuzhiyun  */
hp_mic_jack_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)2907*4882a593Smuzhiyun static int hp_mic_jack_mode_info(struct snd_kcontrol *kcontrol,
2908*4882a593Smuzhiyun 				 struct snd_ctl_elem_info *uinfo)
2909*4882a593Smuzhiyun {
2910*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2911*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2912*4882a593Smuzhiyun 	int out_jacks = get_out_jack_num_items(codec, nid);
2913*4882a593Smuzhiyun 	int in_jacks = get_in_jack_num_items(codec, nid);
2914*4882a593Smuzhiyun 	const char *text = NULL;
2915*4882a593Smuzhiyun 	int idx;
2916*4882a593Smuzhiyun 
2917*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2918*4882a593Smuzhiyun 	uinfo->count = 1;
2919*4882a593Smuzhiyun 	uinfo->value.enumerated.items = out_jacks + in_jacks;
2920*4882a593Smuzhiyun 	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2921*4882a593Smuzhiyun 		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
2922*4882a593Smuzhiyun 	idx = uinfo->value.enumerated.item;
2923*4882a593Smuzhiyun 	if (idx < out_jacks) {
2924*4882a593Smuzhiyun 		if (out_jacks > 1)
2925*4882a593Smuzhiyun 			text = out_jack_texts[idx];
2926*4882a593Smuzhiyun 		else
2927*4882a593Smuzhiyun 			text = "Headphone Out";
2928*4882a593Smuzhiyun 	} else {
2929*4882a593Smuzhiyun 		idx -= out_jacks;
2930*4882a593Smuzhiyun 		if (in_jacks > 1) {
2931*4882a593Smuzhiyun 			unsigned int vref_caps = get_vref_caps(codec, nid);
2932*4882a593Smuzhiyun 			text = vref_texts[get_vref_idx(vref_caps, idx)];
2933*4882a593Smuzhiyun 		} else
2934*4882a593Smuzhiyun 			text = "Mic In";
2935*4882a593Smuzhiyun 	}
2936*4882a593Smuzhiyun 
2937*4882a593Smuzhiyun 	strcpy(uinfo->value.enumerated.name, text);
2938*4882a593Smuzhiyun 	return 0;
2939*4882a593Smuzhiyun }
2940*4882a593Smuzhiyun 
get_cur_hp_mic_jack_mode(struct hda_codec * codec,hda_nid_t nid)2941*4882a593Smuzhiyun static int get_cur_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t nid)
2942*4882a593Smuzhiyun {
2943*4882a593Smuzhiyun 	int out_jacks = get_out_jack_num_items(codec, nid);
2944*4882a593Smuzhiyun 	int in_jacks = get_in_jack_num_items(codec, nid);
2945*4882a593Smuzhiyun 	unsigned int val = snd_hda_codec_get_pin_target(codec, nid);
2946*4882a593Smuzhiyun 	int idx = 0;
2947*4882a593Smuzhiyun 
2948*4882a593Smuzhiyun 	if (val & PIN_OUT) {
2949*4882a593Smuzhiyun 		if (out_jacks > 1 && val == PIN_HP)
2950*4882a593Smuzhiyun 			idx = 1;
2951*4882a593Smuzhiyun 	} else if (val & PIN_IN) {
2952*4882a593Smuzhiyun 		idx = out_jacks;
2953*4882a593Smuzhiyun 		if (in_jacks > 1) {
2954*4882a593Smuzhiyun 			unsigned int vref_caps = get_vref_caps(codec, nid);
2955*4882a593Smuzhiyun 			val &= AC_PINCTL_VREFEN;
2956*4882a593Smuzhiyun 			idx += cvt_from_vref_idx(vref_caps, val);
2957*4882a593Smuzhiyun 		}
2958*4882a593Smuzhiyun 	}
2959*4882a593Smuzhiyun 	return idx;
2960*4882a593Smuzhiyun }
2961*4882a593Smuzhiyun 
hp_mic_jack_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2962*4882a593Smuzhiyun static int hp_mic_jack_mode_get(struct snd_kcontrol *kcontrol,
2963*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
2964*4882a593Smuzhiyun {
2965*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2966*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2967*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] =
2968*4882a593Smuzhiyun 		get_cur_hp_mic_jack_mode(codec, nid);
2969*4882a593Smuzhiyun 	return 0;
2970*4882a593Smuzhiyun }
2971*4882a593Smuzhiyun 
hp_mic_jack_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2972*4882a593Smuzhiyun static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol,
2973*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
2974*4882a593Smuzhiyun {
2975*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
2976*4882a593Smuzhiyun 	hda_nid_t nid = kcontrol->private_value;
2977*4882a593Smuzhiyun 	int out_jacks = get_out_jack_num_items(codec, nid);
2978*4882a593Smuzhiyun 	int in_jacks = get_in_jack_num_items(codec, nid);
2979*4882a593Smuzhiyun 	unsigned int val, oldval, idx;
2980*4882a593Smuzhiyun 
2981*4882a593Smuzhiyun 	oldval = get_cur_hp_mic_jack_mode(codec, nid);
2982*4882a593Smuzhiyun 	idx = ucontrol->value.enumerated.item[0];
2983*4882a593Smuzhiyun 	if (oldval == idx)
2984*4882a593Smuzhiyun 		return 0;
2985*4882a593Smuzhiyun 
2986*4882a593Smuzhiyun 	if (idx < out_jacks) {
2987*4882a593Smuzhiyun 		if (out_jacks > 1)
2988*4882a593Smuzhiyun 			val = idx ? PIN_HP : PIN_OUT;
2989*4882a593Smuzhiyun 		else
2990*4882a593Smuzhiyun 			val = PIN_HP;
2991*4882a593Smuzhiyun 	} else {
2992*4882a593Smuzhiyun 		idx -= out_jacks;
2993*4882a593Smuzhiyun 		if (in_jacks > 1) {
2994*4882a593Smuzhiyun 			unsigned int vref_caps = get_vref_caps(codec, nid);
2995*4882a593Smuzhiyun 			val = snd_hda_codec_get_pin_target(codec, nid);
2996*4882a593Smuzhiyun 			val &= ~(AC_PINCTL_VREFEN | PIN_HP);
2997*4882a593Smuzhiyun 			val |= get_vref_idx(vref_caps, idx) | PIN_IN;
2998*4882a593Smuzhiyun 		} else
2999*4882a593Smuzhiyun 			val = snd_hda_get_default_vref(codec, nid) | PIN_IN;
3000*4882a593Smuzhiyun 	}
3001*4882a593Smuzhiyun 	snd_hda_set_pin_ctl_cache(codec, nid, val);
3002*4882a593Smuzhiyun 	call_hp_automute(codec, NULL);
3003*4882a593Smuzhiyun 
3004*4882a593Smuzhiyun 	return 1;
3005*4882a593Smuzhiyun }
3006*4882a593Smuzhiyun 
3007*4882a593Smuzhiyun static const struct snd_kcontrol_new hp_mic_jack_mode_enum = {
3008*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3009*4882a593Smuzhiyun 	.info = hp_mic_jack_mode_info,
3010*4882a593Smuzhiyun 	.get = hp_mic_jack_mode_get,
3011*4882a593Smuzhiyun 	.put = hp_mic_jack_mode_put,
3012*4882a593Smuzhiyun };
3013*4882a593Smuzhiyun 
create_hp_mic_jack_mode(struct hda_codec * codec,hda_nid_t pin)3014*4882a593Smuzhiyun static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin)
3015*4882a593Smuzhiyun {
3016*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3017*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew;
3018*4882a593Smuzhiyun 
3019*4882a593Smuzhiyun 	knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode",
3020*4882a593Smuzhiyun 				    &hp_mic_jack_mode_enum);
3021*4882a593Smuzhiyun 	if (!knew)
3022*4882a593Smuzhiyun 		return -ENOMEM;
3023*4882a593Smuzhiyun 	knew->private_value = pin;
3024*4882a593Smuzhiyun 	spec->hp_mic_jack_modes = 1;
3025*4882a593Smuzhiyun 	return 0;
3026*4882a593Smuzhiyun }
3027*4882a593Smuzhiyun 
3028*4882a593Smuzhiyun /*
3029*4882a593Smuzhiyun  * Parse input paths
3030*4882a593Smuzhiyun  */
3031*4882a593Smuzhiyun 
3032*4882a593Smuzhiyun /* add the powersave loopback-list entry */
add_loopback_list(struct hda_gen_spec * spec,hda_nid_t mix,int idx)3033*4882a593Smuzhiyun static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx)
3034*4882a593Smuzhiyun {
3035*4882a593Smuzhiyun 	struct hda_amp_list *list;
3036*4882a593Smuzhiyun 
3037*4882a593Smuzhiyun 	list = snd_array_new(&spec->loopback_list);
3038*4882a593Smuzhiyun 	if (!list)
3039*4882a593Smuzhiyun 		return -ENOMEM;
3040*4882a593Smuzhiyun 	list->nid = mix;
3041*4882a593Smuzhiyun 	list->dir = HDA_INPUT;
3042*4882a593Smuzhiyun 	list->idx = idx;
3043*4882a593Smuzhiyun 	spec->loopback.amplist = spec->loopback_list.list;
3044*4882a593Smuzhiyun 	return 0;
3045*4882a593Smuzhiyun }
3046*4882a593Smuzhiyun 
3047*4882a593Smuzhiyun /* return true if either a volume or a mute amp is found for the given
3048*4882a593Smuzhiyun  * aamix path; the amp has to be either in the mixer node or its direct leaf
3049*4882a593Smuzhiyun  */
look_for_mix_leaf_ctls(struct hda_codec * codec,hda_nid_t mix_nid,hda_nid_t pin,unsigned int * mix_val,unsigned int * mute_val)3050*4882a593Smuzhiyun static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid,
3051*4882a593Smuzhiyun 				   hda_nid_t pin, unsigned int *mix_val,
3052*4882a593Smuzhiyun 				   unsigned int *mute_val)
3053*4882a593Smuzhiyun {
3054*4882a593Smuzhiyun 	int idx, num_conns;
3055*4882a593Smuzhiyun 	const hda_nid_t *list;
3056*4882a593Smuzhiyun 	hda_nid_t nid;
3057*4882a593Smuzhiyun 
3058*4882a593Smuzhiyun 	idx = snd_hda_get_conn_index(codec, mix_nid, pin, true);
3059*4882a593Smuzhiyun 	if (idx < 0)
3060*4882a593Smuzhiyun 		return false;
3061*4882a593Smuzhiyun 
3062*4882a593Smuzhiyun 	*mix_val = *mute_val = 0;
3063*4882a593Smuzhiyun 	if (nid_has_volume(codec, mix_nid, HDA_INPUT))
3064*4882a593Smuzhiyun 		*mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
3065*4882a593Smuzhiyun 	if (nid_has_mute(codec, mix_nid, HDA_INPUT))
3066*4882a593Smuzhiyun 		*mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT);
3067*4882a593Smuzhiyun 	if (*mix_val && *mute_val)
3068*4882a593Smuzhiyun 		return true;
3069*4882a593Smuzhiyun 
3070*4882a593Smuzhiyun 	/* check leaf node */
3071*4882a593Smuzhiyun 	num_conns = snd_hda_get_conn_list(codec, mix_nid, &list);
3072*4882a593Smuzhiyun 	if (num_conns < idx)
3073*4882a593Smuzhiyun 		return false;
3074*4882a593Smuzhiyun 	nid = list[idx];
3075*4882a593Smuzhiyun 	if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT) &&
3076*4882a593Smuzhiyun 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_VOL_CTL))
3077*4882a593Smuzhiyun 		*mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3078*4882a593Smuzhiyun 	if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT) &&
3079*4882a593Smuzhiyun 	    !is_ctl_associated(codec, nid, HDA_OUTPUT, 0, NID_PATH_MUTE_CTL))
3080*4882a593Smuzhiyun 		*mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3081*4882a593Smuzhiyun 
3082*4882a593Smuzhiyun 	return *mix_val || *mute_val;
3083*4882a593Smuzhiyun }
3084*4882a593Smuzhiyun 
3085*4882a593Smuzhiyun /* create input playback/capture controls for the given pin */
new_analog_input(struct hda_codec * codec,int input_idx,hda_nid_t pin,const char * ctlname,int ctlidx,hda_nid_t mix_nid)3086*4882a593Smuzhiyun static int new_analog_input(struct hda_codec *codec, int input_idx,
3087*4882a593Smuzhiyun 			    hda_nid_t pin, const char *ctlname, int ctlidx,
3088*4882a593Smuzhiyun 			    hda_nid_t mix_nid)
3089*4882a593Smuzhiyun {
3090*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3091*4882a593Smuzhiyun 	struct nid_path *path;
3092*4882a593Smuzhiyun 	unsigned int mix_val, mute_val;
3093*4882a593Smuzhiyun 	int err, idx;
3094*4882a593Smuzhiyun 
3095*4882a593Smuzhiyun 	if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val))
3096*4882a593Smuzhiyun 		return 0;
3097*4882a593Smuzhiyun 
3098*4882a593Smuzhiyun 	path = snd_hda_add_new_path(codec, pin, mix_nid, 0);
3099*4882a593Smuzhiyun 	if (!path)
3100*4882a593Smuzhiyun 		return -EINVAL;
3101*4882a593Smuzhiyun 	print_nid_path(codec, "loopback", path);
3102*4882a593Smuzhiyun 	spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path);
3103*4882a593Smuzhiyun 
3104*4882a593Smuzhiyun 	idx = path->idx[path->depth - 1];
3105*4882a593Smuzhiyun 	if (mix_val) {
3106*4882a593Smuzhiyun 		err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val);
3107*4882a593Smuzhiyun 		if (err < 0)
3108*4882a593Smuzhiyun 			return err;
3109*4882a593Smuzhiyun 		path->ctls[NID_PATH_VOL_CTL] = mix_val;
3110*4882a593Smuzhiyun 	}
3111*4882a593Smuzhiyun 
3112*4882a593Smuzhiyun 	if (mute_val) {
3113*4882a593Smuzhiyun 		err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val);
3114*4882a593Smuzhiyun 		if (err < 0)
3115*4882a593Smuzhiyun 			return err;
3116*4882a593Smuzhiyun 		path->ctls[NID_PATH_MUTE_CTL] = mute_val;
3117*4882a593Smuzhiyun 	}
3118*4882a593Smuzhiyun 
3119*4882a593Smuzhiyun 	path->active = true;
3120*4882a593Smuzhiyun 	path->stream_enabled = true; /* no DAC/ADC involved */
3121*4882a593Smuzhiyun 	err = add_loopback_list(spec, mix_nid, idx);
3122*4882a593Smuzhiyun 	if (err < 0)
3123*4882a593Smuzhiyun 		return err;
3124*4882a593Smuzhiyun 
3125*4882a593Smuzhiyun 	if (spec->mixer_nid != spec->mixer_merge_nid &&
3126*4882a593Smuzhiyun 	    !spec->loopback_merge_path) {
3127*4882a593Smuzhiyun 		path = snd_hda_add_new_path(codec, spec->mixer_nid,
3128*4882a593Smuzhiyun 					    spec->mixer_merge_nid, 0);
3129*4882a593Smuzhiyun 		if (path) {
3130*4882a593Smuzhiyun 			print_nid_path(codec, "loopback-merge", path);
3131*4882a593Smuzhiyun 			path->active = true;
3132*4882a593Smuzhiyun 			path->pin_fixed = true; /* static route */
3133*4882a593Smuzhiyun 			path->stream_enabled = true; /* no DAC/ADC involved */
3134*4882a593Smuzhiyun 			spec->loopback_merge_path =
3135*4882a593Smuzhiyun 				snd_hda_get_path_idx(codec, path);
3136*4882a593Smuzhiyun 		}
3137*4882a593Smuzhiyun 	}
3138*4882a593Smuzhiyun 
3139*4882a593Smuzhiyun 	return 0;
3140*4882a593Smuzhiyun }
3141*4882a593Smuzhiyun 
is_input_pin(struct hda_codec * codec,hda_nid_t nid)3142*4882a593Smuzhiyun static int is_input_pin(struct hda_codec *codec, hda_nid_t nid)
3143*4882a593Smuzhiyun {
3144*4882a593Smuzhiyun 	unsigned int pincap = snd_hda_query_pin_caps(codec, nid);
3145*4882a593Smuzhiyun 	return (pincap & AC_PINCAP_IN) != 0;
3146*4882a593Smuzhiyun }
3147*4882a593Smuzhiyun 
3148*4882a593Smuzhiyun /* Parse the codec tree and retrieve ADCs */
fill_adc_nids(struct hda_codec * codec)3149*4882a593Smuzhiyun static int fill_adc_nids(struct hda_codec *codec)
3150*4882a593Smuzhiyun {
3151*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3152*4882a593Smuzhiyun 	hda_nid_t nid;
3153*4882a593Smuzhiyun 	hda_nid_t *adc_nids = spec->adc_nids;
3154*4882a593Smuzhiyun 	int max_nums = ARRAY_SIZE(spec->adc_nids);
3155*4882a593Smuzhiyun 	int nums = 0;
3156*4882a593Smuzhiyun 
3157*4882a593Smuzhiyun 	for_each_hda_codec_node(nid, codec) {
3158*4882a593Smuzhiyun 		unsigned int caps = get_wcaps(codec, nid);
3159*4882a593Smuzhiyun 		int type = get_wcaps_type(caps);
3160*4882a593Smuzhiyun 
3161*4882a593Smuzhiyun 		if (type != AC_WID_AUD_IN || (caps & AC_WCAP_DIGITAL))
3162*4882a593Smuzhiyun 			continue;
3163*4882a593Smuzhiyun 		adc_nids[nums] = nid;
3164*4882a593Smuzhiyun 		if (++nums >= max_nums)
3165*4882a593Smuzhiyun 			break;
3166*4882a593Smuzhiyun 	}
3167*4882a593Smuzhiyun 	spec->num_adc_nids = nums;
3168*4882a593Smuzhiyun 
3169*4882a593Smuzhiyun 	/* copy the detected ADCs to all_adcs[] */
3170*4882a593Smuzhiyun 	spec->num_all_adcs = nums;
3171*4882a593Smuzhiyun 	memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t));
3172*4882a593Smuzhiyun 
3173*4882a593Smuzhiyun 	return nums;
3174*4882a593Smuzhiyun }
3175*4882a593Smuzhiyun 
3176*4882a593Smuzhiyun /* filter out invalid adc_nids that don't give all active input pins;
3177*4882a593Smuzhiyun  * if needed, check whether dynamic ADC-switching is available
3178*4882a593Smuzhiyun  */
check_dyn_adc_switch(struct hda_codec * codec)3179*4882a593Smuzhiyun static int check_dyn_adc_switch(struct hda_codec *codec)
3180*4882a593Smuzhiyun {
3181*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3182*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
3183*4882a593Smuzhiyun 	unsigned int ok_bits;
3184*4882a593Smuzhiyun 	int i, n, nums;
3185*4882a593Smuzhiyun 
3186*4882a593Smuzhiyun 	nums = 0;
3187*4882a593Smuzhiyun 	ok_bits = 0;
3188*4882a593Smuzhiyun 	for (n = 0; n < spec->num_adc_nids; n++) {
3189*4882a593Smuzhiyun 		for (i = 0; i < imux->num_items; i++) {
3190*4882a593Smuzhiyun 			if (!spec->input_paths[i][n])
3191*4882a593Smuzhiyun 				break;
3192*4882a593Smuzhiyun 		}
3193*4882a593Smuzhiyun 		if (i >= imux->num_items) {
3194*4882a593Smuzhiyun 			ok_bits |= (1 << n);
3195*4882a593Smuzhiyun 			nums++;
3196*4882a593Smuzhiyun 		}
3197*4882a593Smuzhiyun 	}
3198*4882a593Smuzhiyun 
3199*4882a593Smuzhiyun 	if (!ok_bits) {
3200*4882a593Smuzhiyun 		/* check whether ADC-switch is possible */
3201*4882a593Smuzhiyun 		for (i = 0; i < imux->num_items; i++) {
3202*4882a593Smuzhiyun 			for (n = 0; n < spec->num_adc_nids; n++) {
3203*4882a593Smuzhiyun 				if (spec->input_paths[i][n]) {
3204*4882a593Smuzhiyun 					spec->dyn_adc_idx[i] = n;
3205*4882a593Smuzhiyun 					break;
3206*4882a593Smuzhiyun 				}
3207*4882a593Smuzhiyun 			}
3208*4882a593Smuzhiyun 		}
3209*4882a593Smuzhiyun 
3210*4882a593Smuzhiyun 		codec_dbg(codec, "enabling ADC switching\n");
3211*4882a593Smuzhiyun 		spec->dyn_adc_switch = 1;
3212*4882a593Smuzhiyun 	} else if (nums != spec->num_adc_nids) {
3213*4882a593Smuzhiyun 		/* shrink the invalid adcs and input paths */
3214*4882a593Smuzhiyun 		nums = 0;
3215*4882a593Smuzhiyun 		for (n = 0; n < spec->num_adc_nids; n++) {
3216*4882a593Smuzhiyun 			if (!(ok_bits & (1 << n)))
3217*4882a593Smuzhiyun 				continue;
3218*4882a593Smuzhiyun 			if (n != nums) {
3219*4882a593Smuzhiyun 				spec->adc_nids[nums] = spec->adc_nids[n];
3220*4882a593Smuzhiyun 				for (i = 0; i < imux->num_items; i++) {
3221*4882a593Smuzhiyun 					invalidate_nid_path(codec,
3222*4882a593Smuzhiyun 						spec->input_paths[i][nums]);
3223*4882a593Smuzhiyun 					spec->input_paths[i][nums] =
3224*4882a593Smuzhiyun 						spec->input_paths[i][n];
3225*4882a593Smuzhiyun 					spec->input_paths[i][n] = 0;
3226*4882a593Smuzhiyun 				}
3227*4882a593Smuzhiyun 			}
3228*4882a593Smuzhiyun 			nums++;
3229*4882a593Smuzhiyun 		}
3230*4882a593Smuzhiyun 		spec->num_adc_nids = nums;
3231*4882a593Smuzhiyun 	}
3232*4882a593Smuzhiyun 
3233*4882a593Smuzhiyun 	if (imux->num_items == 1 ||
3234*4882a593Smuzhiyun 	    (imux->num_items == 2 && spec->hp_mic)) {
3235*4882a593Smuzhiyun 		codec_dbg(codec, "reducing to a single ADC\n");
3236*4882a593Smuzhiyun 		spec->num_adc_nids = 1; /* reduce to a single ADC */
3237*4882a593Smuzhiyun 	}
3238*4882a593Smuzhiyun 
3239*4882a593Smuzhiyun 	/* single index for individual volumes ctls */
3240*4882a593Smuzhiyun 	if (!spec->dyn_adc_switch && spec->multi_cap_vol)
3241*4882a593Smuzhiyun 		spec->num_adc_nids = 1;
3242*4882a593Smuzhiyun 
3243*4882a593Smuzhiyun 	return 0;
3244*4882a593Smuzhiyun }
3245*4882a593Smuzhiyun 
3246*4882a593Smuzhiyun /* parse capture source paths from the given pin and create imux items */
parse_capture_source(struct hda_codec * codec,hda_nid_t pin,int cfg_idx,int num_adcs,const char * label,int anchor)3247*4882a593Smuzhiyun static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
3248*4882a593Smuzhiyun 				int cfg_idx, int num_adcs,
3249*4882a593Smuzhiyun 				const char *label, int anchor)
3250*4882a593Smuzhiyun {
3251*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3252*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
3253*4882a593Smuzhiyun 	int imux_idx = imux->num_items;
3254*4882a593Smuzhiyun 	bool imux_added = false;
3255*4882a593Smuzhiyun 	int c;
3256*4882a593Smuzhiyun 
3257*4882a593Smuzhiyun 	for (c = 0; c < num_adcs; c++) {
3258*4882a593Smuzhiyun 		struct nid_path *path;
3259*4882a593Smuzhiyun 		hda_nid_t adc = spec->adc_nids[c];
3260*4882a593Smuzhiyun 
3261*4882a593Smuzhiyun 		if (!is_reachable_path(codec, pin, adc))
3262*4882a593Smuzhiyun 			continue;
3263*4882a593Smuzhiyun 		path = snd_hda_add_new_path(codec, pin, adc, anchor);
3264*4882a593Smuzhiyun 		if (!path)
3265*4882a593Smuzhiyun 			continue;
3266*4882a593Smuzhiyun 		print_nid_path(codec, "input", path);
3267*4882a593Smuzhiyun 		spec->input_paths[imux_idx][c] =
3268*4882a593Smuzhiyun 			snd_hda_get_path_idx(codec, path);
3269*4882a593Smuzhiyun 
3270*4882a593Smuzhiyun 		if (!imux_added) {
3271*4882a593Smuzhiyun 			if (spec->hp_mic_pin == pin)
3272*4882a593Smuzhiyun 				spec->hp_mic_mux_idx = imux->num_items;
3273*4882a593Smuzhiyun 			spec->imux_pins[imux->num_items] = pin;
3274*4882a593Smuzhiyun 			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
3275*4882a593Smuzhiyun 			imux_added = true;
3276*4882a593Smuzhiyun 			if (spec->dyn_adc_switch)
3277*4882a593Smuzhiyun 				spec->dyn_adc_idx[imux_idx] = c;
3278*4882a593Smuzhiyun 		}
3279*4882a593Smuzhiyun 	}
3280*4882a593Smuzhiyun 
3281*4882a593Smuzhiyun 	return 0;
3282*4882a593Smuzhiyun }
3283*4882a593Smuzhiyun 
3284*4882a593Smuzhiyun /*
3285*4882a593Smuzhiyun  * create playback/capture controls for input pins
3286*4882a593Smuzhiyun  */
3287*4882a593Smuzhiyun 
3288*4882a593Smuzhiyun /* fill the label for each input at first */
fill_input_pin_labels(struct hda_codec * codec)3289*4882a593Smuzhiyun static int fill_input_pin_labels(struct hda_codec *codec)
3290*4882a593Smuzhiyun {
3291*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3292*4882a593Smuzhiyun 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3293*4882a593Smuzhiyun 	int i;
3294*4882a593Smuzhiyun 
3295*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++) {
3296*4882a593Smuzhiyun 		hda_nid_t pin = cfg->inputs[i].pin;
3297*4882a593Smuzhiyun 		const char *label;
3298*4882a593Smuzhiyun 		int j, idx;
3299*4882a593Smuzhiyun 
3300*4882a593Smuzhiyun 		if (!is_input_pin(codec, pin))
3301*4882a593Smuzhiyun 			continue;
3302*4882a593Smuzhiyun 
3303*4882a593Smuzhiyun 		label = hda_get_autocfg_input_label(codec, cfg, i);
3304*4882a593Smuzhiyun 		idx = 0;
3305*4882a593Smuzhiyun 		for (j = i - 1; j >= 0; j--) {
3306*4882a593Smuzhiyun 			if (spec->input_labels[j] &&
3307*4882a593Smuzhiyun 			    !strcmp(spec->input_labels[j], label)) {
3308*4882a593Smuzhiyun 				idx = spec->input_label_idxs[j] + 1;
3309*4882a593Smuzhiyun 				break;
3310*4882a593Smuzhiyun 			}
3311*4882a593Smuzhiyun 		}
3312*4882a593Smuzhiyun 
3313*4882a593Smuzhiyun 		spec->input_labels[i] = label;
3314*4882a593Smuzhiyun 		spec->input_label_idxs[i] = idx;
3315*4882a593Smuzhiyun 	}
3316*4882a593Smuzhiyun 
3317*4882a593Smuzhiyun 	return 0;
3318*4882a593Smuzhiyun }
3319*4882a593Smuzhiyun 
3320*4882a593Smuzhiyun #define CFG_IDX_MIX	99	/* a dummy cfg->input idx for stereo mix */
3321*4882a593Smuzhiyun 
create_input_ctls(struct hda_codec * codec)3322*4882a593Smuzhiyun static int create_input_ctls(struct hda_codec *codec)
3323*4882a593Smuzhiyun {
3324*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3325*4882a593Smuzhiyun 	const struct auto_pin_cfg *cfg = &spec->autocfg;
3326*4882a593Smuzhiyun 	hda_nid_t mixer = spec->mixer_nid;
3327*4882a593Smuzhiyun 	int num_adcs;
3328*4882a593Smuzhiyun 	int i, err;
3329*4882a593Smuzhiyun 	unsigned int val;
3330*4882a593Smuzhiyun 
3331*4882a593Smuzhiyun 	num_adcs = fill_adc_nids(codec);
3332*4882a593Smuzhiyun 	if (num_adcs < 0)
3333*4882a593Smuzhiyun 		return 0;
3334*4882a593Smuzhiyun 
3335*4882a593Smuzhiyun 	err = fill_input_pin_labels(codec);
3336*4882a593Smuzhiyun 	if (err < 0)
3337*4882a593Smuzhiyun 		return err;
3338*4882a593Smuzhiyun 
3339*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++) {
3340*4882a593Smuzhiyun 		hda_nid_t pin;
3341*4882a593Smuzhiyun 
3342*4882a593Smuzhiyun 		pin = cfg->inputs[i].pin;
3343*4882a593Smuzhiyun 		if (!is_input_pin(codec, pin))
3344*4882a593Smuzhiyun 			continue;
3345*4882a593Smuzhiyun 
3346*4882a593Smuzhiyun 		val = PIN_IN;
3347*4882a593Smuzhiyun 		if (cfg->inputs[i].type == AUTO_PIN_MIC)
3348*4882a593Smuzhiyun 			val |= snd_hda_get_default_vref(codec, pin);
3349*4882a593Smuzhiyun 		if (pin != spec->hp_mic_pin &&
3350*4882a593Smuzhiyun 		    !snd_hda_codec_get_pin_target(codec, pin))
3351*4882a593Smuzhiyun 			set_pin_target(codec, pin, val, false);
3352*4882a593Smuzhiyun 
3353*4882a593Smuzhiyun 		if (mixer) {
3354*4882a593Smuzhiyun 			if (is_reachable_path(codec, pin, mixer)) {
3355*4882a593Smuzhiyun 				err = new_analog_input(codec, i, pin,
3356*4882a593Smuzhiyun 						       spec->input_labels[i],
3357*4882a593Smuzhiyun 						       spec->input_label_idxs[i],
3358*4882a593Smuzhiyun 						       mixer);
3359*4882a593Smuzhiyun 				if (err < 0)
3360*4882a593Smuzhiyun 					return err;
3361*4882a593Smuzhiyun 			}
3362*4882a593Smuzhiyun 		}
3363*4882a593Smuzhiyun 
3364*4882a593Smuzhiyun 		err = parse_capture_source(codec, pin, i, num_adcs,
3365*4882a593Smuzhiyun 					   spec->input_labels[i], -mixer);
3366*4882a593Smuzhiyun 		if (err < 0)
3367*4882a593Smuzhiyun 			return err;
3368*4882a593Smuzhiyun 
3369*4882a593Smuzhiyun 		if (spec->add_jack_modes) {
3370*4882a593Smuzhiyun 			err = create_in_jack_mode(codec, pin);
3371*4882a593Smuzhiyun 			if (err < 0)
3372*4882a593Smuzhiyun 				return err;
3373*4882a593Smuzhiyun 		}
3374*4882a593Smuzhiyun 	}
3375*4882a593Smuzhiyun 
3376*4882a593Smuzhiyun 	/* add stereo mix when explicitly enabled via hint */
3377*4882a593Smuzhiyun 	if (mixer && spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_ENABLE) {
3378*4882a593Smuzhiyun 		err = parse_capture_source(codec, mixer, CFG_IDX_MIX, num_adcs,
3379*4882a593Smuzhiyun 					   "Stereo Mix", 0);
3380*4882a593Smuzhiyun 		if (err < 0)
3381*4882a593Smuzhiyun 			return err;
3382*4882a593Smuzhiyun 		else
3383*4882a593Smuzhiyun 			spec->suppress_auto_mic = 1;
3384*4882a593Smuzhiyun 	}
3385*4882a593Smuzhiyun 
3386*4882a593Smuzhiyun 	return 0;
3387*4882a593Smuzhiyun }
3388*4882a593Smuzhiyun 
3389*4882a593Smuzhiyun 
3390*4882a593Smuzhiyun /*
3391*4882a593Smuzhiyun  * input source mux
3392*4882a593Smuzhiyun  */
3393*4882a593Smuzhiyun 
3394*4882a593Smuzhiyun /* get the input path specified by the given adc and imux indices */
get_input_path(struct hda_codec * codec,int adc_idx,int imux_idx)3395*4882a593Smuzhiyun static struct nid_path *get_input_path(struct hda_codec *codec, int adc_idx, int imux_idx)
3396*4882a593Smuzhiyun {
3397*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3398*4882a593Smuzhiyun 	if (imux_idx < 0 || imux_idx >= HDA_MAX_NUM_INPUTS) {
3399*4882a593Smuzhiyun 		snd_BUG();
3400*4882a593Smuzhiyun 		return NULL;
3401*4882a593Smuzhiyun 	}
3402*4882a593Smuzhiyun 	if (spec->dyn_adc_switch)
3403*4882a593Smuzhiyun 		adc_idx = spec->dyn_adc_idx[imux_idx];
3404*4882a593Smuzhiyun 	if (adc_idx < 0 || adc_idx >= AUTO_CFG_MAX_INS) {
3405*4882a593Smuzhiyun 		snd_BUG();
3406*4882a593Smuzhiyun 		return NULL;
3407*4882a593Smuzhiyun 	}
3408*4882a593Smuzhiyun 	return snd_hda_get_path_from_idx(codec, spec->input_paths[imux_idx][adc_idx]);
3409*4882a593Smuzhiyun }
3410*4882a593Smuzhiyun 
3411*4882a593Smuzhiyun static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
3412*4882a593Smuzhiyun 		      unsigned int idx);
3413*4882a593Smuzhiyun 
mux_enum_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)3414*4882a593Smuzhiyun static int mux_enum_info(struct snd_kcontrol *kcontrol,
3415*4882a593Smuzhiyun 			 struct snd_ctl_elem_info *uinfo)
3416*4882a593Smuzhiyun {
3417*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3418*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3419*4882a593Smuzhiyun 	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
3420*4882a593Smuzhiyun }
3421*4882a593Smuzhiyun 
mux_enum_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3422*4882a593Smuzhiyun static int mux_enum_get(struct snd_kcontrol *kcontrol,
3423*4882a593Smuzhiyun 			struct snd_ctl_elem_value *ucontrol)
3424*4882a593Smuzhiyun {
3425*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3426*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3427*4882a593Smuzhiyun 	/* the ctls are created at once with multiple counts */
3428*4882a593Smuzhiyun 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3429*4882a593Smuzhiyun 
3430*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
3431*4882a593Smuzhiyun 	return 0;
3432*4882a593Smuzhiyun }
3433*4882a593Smuzhiyun 
mux_enum_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3434*4882a593Smuzhiyun static int mux_enum_put(struct snd_kcontrol *kcontrol,
3435*4882a593Smuzhiyun 			    struct snd_ctl_elem_value *ucontrol)
3436*4882a593Smuzhiyun {
3437*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3438*4882a593Smuzhiyun 	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
3439*4882a593Smuzhiyun 	return mux_select(codec, adc_idx,
3440*4882a593Smuzhiyun 			  ucontrol->value.enumerated.item[0]);
3441*4882a593Smuzhiyun }
3442*4882a593Smuzhiyun 
3443*4882a593Smuzhiyun static const struct snd_kcontrol_new cap_src_temp = {
3444*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3445*4882a593Smuzhiyun 	.name = "Input Source",
3446*4882a593Smuzhiyun 	.info = mux_enum_info,
3447*4882a593Smuzhiyun 	.get = mux_enum_get,
3448*4882a593Smuzhiyun 	.put = mux_enum_put,
3449*4882a593Smuzhiyun };
3450*4882a593Smuzhiyun 
3451*4882a593Smuzhiyun /*
3452*4882a593Smuzhiyun  * capture volume and capture switch ctls
3453*4882a593Smuzhiyun  */
3454*4882a593Smuzhiyun 
3455*4882a593Smuzhiyun typedef int (*put_call_t)(struct snd_kcontrol *kcontrol,
3456*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol);
3457*4882a593Smuzhiyun 
3458*4882a593Smuzhiyun /* call the given amp update function for all amps in the imux list at once */
cap_put_caller(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol,put_call_t func,int type)3459*4882a593Smuzhiyun static int cap_put_caller(struct snd_kcontrol *kcontrol,
3460*4882a593Smuzhiyun 			  struct snd_ctl_elem_value *ucontrol,
3461*4882a593Smuzhiyun 			  put_call_t func, int type)
3462*4882a593Smuzhiyun {
3463*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3464*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3465*4882a593Smuzhiyun 	const struct hda_input_mux *imux;
3466*4882a593Smuzhiyun 	struct nid_path *path;
3467*4882a593Smuzhiyun 	int i, adc_idx, ret, err = 0;
3468*4882a593Smuzhiyun 
3469*4882a593Smuzhiyun 	imux = &spec->input_mux;
3470*4882a593Smuzhiyun 	adc_idx = kcontrol->id.index;
3471*4882a593Smuzhiyun 	mutex_lock(&codec->control_mutex);
3472*4882a593Smuzhiyun 	for (i = 0; i < imux->num_items; i++) {
3473*4882a593Smuzhiyun 		path = get_input_path(codec, adc_idx, i);
3474*4882a593Smuzhiyun 		if (!path || !path->ctls[type])
3475*4882a593Smuzhiyun 			continue;
3476*4882a593Smuzhiyun 		kcontrol->private_value = path->ctls[type];
3477*4882a593Smuzhiyun 		ret = func(kcontrol, ucontrol);
3478*4882a593Smuzhiyun 		if (ret < 0) {
3479*4882a593Smuzhiyun 			err = ret;
3480*4882a593Smuzhiyun 			break;
3481*4882a593Smuzhiyun 		}
3482*4882a593Smuzhiyun 		if (ret > 0)
3483*4882a593Smuzhiyun 			err = 1;
3484*4882a593Smuzhiyun 	}
3485*4882a593Smuzhiyun 	mutex_unlock(&codec->control_mutex);
3486*4882a593Smuzhiyun 	if (err >= 0 && spec->cap_sync_hook)
3487*4882a593Smuzhiyun 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3488*4882a593Smuzhiyun 	return err;
3489*4882a593Smuzhiyun }
3490*4882a593Smuzhiyun 
3491*4882a593Smuzhiyun /* capture volume ctl callbacks */
3492*4882a593Smuzhiyun #define cap_vol_info		snd_hda_mixer_amp_volume_info
3493*4882a593Smuzhiyun #define cap_vol_get		snd_hda_mixer_amp_volume_get
3494*4882a593Smuzhiyun #define cap_vol_tlv		snd_hda_mixer_amp_tlv
3495*4882a593Smuzhiyun 
cap_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3496*4882a593Smuzhiyun static int cap_vol_put(struct snd_kcontrol *kcontrol,
3497*4882a593Smuzhiyun 		       struct snd_ctl_elem_value *ucontrol)
3498*4882a593Smuzhiyun {
3499*4882a593Smuzhiyun 	return cap_put_caller(kcontrol, ucontrol,
3500*4882a593Smuzhiyun 			      snd_hda_mixer_amp_volume_put,
3501*4882a593Smuzhiyun 			      NID_PATH_VOL_CTL);
3502*4882a593Smuzhiyun }
3503*4882a593Smuzhiyun 
3504*4882a593Smuzhiyun static const struct snd_kcontrol_new cap_vol_temp = {
3505*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3506*4882a593Smuzhiyun 	.name = "Capture Volume",
3507*4882a593Smuzhiyun 	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
3508*4882a593Smuzhiyun 		   SNDRV_CTL_ELEM_ACCESS_TLV_READ |
3509*4882a593Smuzhiyun 		   SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK),
3510*4882a593Smuzhiyun 	.info = cap_vol_info,
3511*4882a593Smuzhiyun 	.get = cap_vol_get,
3512*4882a593Smuzhiyun 	.put = cap_vol_put,
3513*4882a593Smuzhiyun 	.tlv = { .c = cap_vol_tlv },
3514*4882a593Smuzhiyun };
3515*4882a593Smuzhiyun 
3516*4882a593Smuzhiyun /* capture switch ctl callbacks */
3517*4882a593Smuzhiyun #define cap_sw_info		snd_ctl_boolean_stereo_info
3518*4882a593Smuzhiyun #define cap_sw_get		snd_hda_mixer_amp_switch_get
3519*4882a593Smuzhiyun 
cap_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3520*4882a593Smuzhiyun static int cap_sw_put(struct snd_kcontrol *kcontrol,
3521*4882a593Smuzhiyun 		      struct snd_ctl_elem_value *ucontrol)
3522*4882a593Smuzhiyun {
3523*4882a593Smuzhiyun 	return cap_put_caller(kcontrol, ucontrol,
3524*4882a593Smuzhiyun 			      snd_hda_mixer_amp_switch_put,
3525*4882a593Smuzhiyun 			      NID_PATH_MUTE_CTL);
3526*4882a593Smuzhiyun }
3527*4882a593Smuzhiyun 
3528*4882a593Smuzhiyun static const struct snd_kcontrol_new cap_sw_temp = {
3529*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
3530*4882a593Smuzhiyun 	.name = "Capture Switch",
3531*4882a593Smuzhiyun 	.info = cap_sw_info,
3532*4882a593Smuzhiyun 	.get = cap_sw_get,
3533*4882a593Smuzhiyun 	.put = cap_sw_put,
3534*4882a593Smuzhiyun };
3535*4882a593Smuzhiyun 
parse_capvol_in_path(struct hda_codec * codec,struct nid_path * path)3536*4882a593Smuzhiyun static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
3537*4882a593Smuzhiyun {
3538*4882a593Smuzhiyun 	hda_nid_t nid;
3539*4882a593Smuzhiyun 	int i, depth;
3540*4882a593Smuzhiyun 
3541*4882a593Smuzhiyun 	path->ctls[NID_PATH_VOL_CTL] = path->ctls[NID_PATH_MUTE_CTL] = 0;
3542*4882a593Smuzhiyun 	for (depth = 0; depth < 3; depth++) {
3543*4882a593Smuzhiyun 		if (depth >= path->depth)
3544*4882a593Smuzhiyun 			return -EINVAL;
3545*4882a593Smuzhiyun 		i = path->depth - depth - 1;
3546*4882a593Smuzhiyun 		nid = path->path[i];
3547*4882a593Smuzhiyun 		if (!path->ctls[NID_PATH_VOL_CTL]) {
3548*4882a593Smuzhiyun 			if (nid_has_volume(codec, nid, HDA_OUTPUT))
3549*4882a593Smuzhiyun 				path->ctls[NID_PATH_VOL_CTL] =
3550*4882a593Smuzhiyun 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3551*4882a593Smuzhiyun 			else if (nid_has_volume(codec, nid, HDA_INPUT)) {
3552*4882a593Smuzhiyun 				int idx = path->idx[i];
3553*4882a593Smuzhiyun 				if (!depth && codec->single_adc_amp)
3554*4882a593Smuzhiyun 					idx = 0;
3555*4882a593Smuzhiyun 				path->ctls[NID_PATH_VOL_CTL] =
3556*4882a593Smuzhiyun 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3557*4882a593Smuzhiyun 			}
3558*4882a593Smuzhiyun 		}
3559*4882a593Smuzhiyun 		if (!path->ctls[NID_PATH_MUTE_CTL]) {
3560*4882a593Smuzhiyun 			if (nid_has_mute(codec, nid, HDA_OUTPUT))
3561*4882a593Smuzhiyun 				path->ctls[NID_PATH_MUTE_CTL] =
3562*4882a593Smuzhiyun 					HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3563*4882a593Smuzhiyun 			else if (nid_has_mute(codec, nid, HDA_INPUT)) {
3564*4882a593Smuzhiyun 				int idx = path->idx[i];
3565*4882a593Smuzhiyun 				if (!depth && codec->single_adc_amp)
3566*4882a593Smuzhiyun 					idx = 0;
3567*4882a593Smuzhiyun 				path->ctls[NID_PATH_MUTE_CTL] =
3568*4882a593Smuzhiyun 					HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_INPUT);
3569*4882a593Smuzhiyun 			}
3570*4882a593Smuzhiyun 		}
3571*4882a593Smuzhiyun 	}
3572*4882a593Smuzhiyun 	return 0;
3573*4882a593Smuzhiyun }
3574*4882a593Smuzhiyun 
is_inv_dmic_pin(struct hda_codec * codec,hda_nid_t nid)3575*4882a593Smuzhiyun static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
3576*4882a593Smuzhiyun {
3577*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3578*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
3579*4882a593Smuzhiyun 	unsigned int val;
3580*4882a593Smuzhiyun 	int i;
3581*4882a593Smuzhiyun 
3582*4882a593Smuzhiyun 	if (!spec->inv_dmic_split)
3583*4882a593Smuzhiyun 		return false;
3584*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++) {
3585*4882a593Smuzhiyun 		if (cfg->inputs[i].pin != nid)
3586*4882a593Smuzhiyun 			continue;
3587*4882a593Smuzhiyun 		if (cfg->inputs[i].type != AUTO_PIN_MIC)
3588*4882a593Smuzhiyun 			return false;
3589*4882a593Smuzhiyun 		val = snd_hda_codec_get_pincfg(codec, nid);
3590*4882a593Smuzhiyun 		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
3591*4882a593Smuzhiyun 	}
3592*4882a593Smuzhiyun 	return false;
3593*4882a593Smuzhiyun }
3594*4882a593Smuzhiyun 
3595*4882a593Smuzhiyun /* capture switch put callback for a single control with hook call */
cap_single_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)3596*4882a593Smuzhiyun static int cap_single_sw_put(struct snd_kcontrol *kcontrol,
3597*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
3598*4882a593Smuzhiyun {
3599*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3600*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3601*4882a593Smuzhiyun 	int ret;
3602*4882a593Smuzhiyun 
3603*4882a593Smuzhiyun 	ret = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
3604*4882a593Smuzhiyun 	if (ret < 0)
3605*4882a593Smuzhiyun 		return ret;
3606*4882a593Smuzhiyun 
3607*4882a593Smuzhiyun 	if (spec->cap_sync_hook)
3608*4882a593Smuzhiyun 		spec->cap_sync_hook(codec, kcontrol, ucontrol);
3609*4882a593Smuzhiyun 
3610*4882a593Smuzhiyun 	return ret;
3611*4882a593Smuzhiyun }
3612*4882a593Smuzhiyun 
add_single_cap_ctl(struct hda_codec * codec,const char * label,int idx,bool is_switch,unsigned int ctl,bool inv_dmic)3613*4882a593Smuzhiyun static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
3614*4882a593Smuzhiyun 			      int idx, bool is_switch, unsigned int ctl,
3615*4882a593Smuzhiyun 			      bool inv_dmic)
3616*4882a593Smuzhiyun {
3617*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3618*4882a593Smuzhiyun 	char tmpname[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3619*4882a593Smuzhiyun 	int type = is_switch ? HDA_CTL_WIDGET_MUTE : HDA_CTL_WIDGET_VOL;
3620*4882a593Smuzhiyun 	const char *sfx = is_switch ? "Switch" : "Volume";
3621*4882a593Smuzhiyun 	unsigned int chs = inv_dmic ? 1 : 3;
3622*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew;
3623*4882a593Smuzhiyun 
3624*4882a593Smuzhiyun 	if (!ctl)
3625*4882a593Smuzhiyun 		return 0;
3626*4882a593Smuzhiyun 
3627*4882a593Smuzhiyun 	if (label)
3628*4882a593Smuzhiyun 		snprintf(tmpname, sizeof(tmpname),
3629*4882a593Smuzhiyun 			 "%s Capture %s", label, sfx);
3630*4882a593Smuzhiyun 	else
3631*4882a593Smuzhiyun 		snprintf(tmpname, sizeof(tmpname),
3632*4882a593Smuzhiyun 			 "Capture %s", sfx);
3633*4882a593Smuzhiyun 	knew = add_control(spec, type, tmpname, idx,
3634*4882a593Smuzhiyun 			   amp_val_replace_channels(ctl, chs));
3635*4882a593Smuzhiyun 	if (!knew)
3636*4882a593Smuzhiyun 		return -ENOMEM;
3637*4882a593Smuzhiyun 	if (is_switch)
3638*4882a593Smuzhiyun 		knew->put = cap_single_sw_put;
3639*4882a593Smuzhiyun 	if (!inv_dmic)
3640*4882a593Smuzhiyun 		return 0;
3641*4882a593Smuzhiyun 
3642*4882a593Smuzhiyun 	/* Make independent right kcontrol */
3643*4882a593Smuzhiyun 	if (label)
3644*4882a593Smuzhiyun 		snprintf(tmpname, sizeof(tmpname),
3645*4882a593Smuzhiyun 			 "Inverted %s Capture %s", label, sfx);
3646*4882a593Smuzhiyun 	else
3647*4882a593Smuzhiyun 		snprintf(tmpname, sizeof(tmpname),
3648*4882a593Smuzhiyun 			 "Inverted Capture %s", sfx);
3649*4882a593Smuzhiyun 	knew = add_control(spec, type, tmpname, idx,
3650*4882a593Smuzhiyun 			   amp_val_replace_channels(ctl, 2));
3651*4882a593Smuzhiyun 	if (!knew)
3652*4882a593Smuzhiyun 		return -ENOMEM;
3653*4882a593Smuzhiyun 	if (is_switch)
3654*4882a593Smuzhiyun 		knew->put = cap_single_sw_put;
3655*4882a593Smuzhiyun 	return 0;
3656*4882a593Smuzhiyun }
3657*4882a593Smuzhiyun 
3658*4882a593Smuzhiyun /* create single (and simple) capture volume and switch controls */
create_single_cap_vol_ctl(struct hda_codec * codec,int idx,unsigned int vol_ctl,unsigned int sw_ctl,bool inv_dmic)3659*4882a593Smuzhiyun static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
3660*4882a593Smuzhiyun 				     unsigned int vol_ctl, unsigned int sw_ctl,
3661*4882a593Smuzhiyun 				     bool inv_dmic)
3662*4882a593Smuzhiyun {
3663*4882a593Smuzhiyun 	int err;
3664*4882a593Smuzhiyun 	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
3665*4882a593Smuzhiyun 	if (err < 0)
3666*4882a593Smuzhiyun 		return err;
3667*4882a593Smuzhiyun 	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
3668*4882a593Smuzhiyun 	if (err < 0)
3669*4882a593Smuzhiyun 		return err;
3670*4882a593Smuzhiyun 	return 0;
3671*4882a593Smuzhiyun }
3672*4882a593Smuzhiyun 
3673*4882a593Smuzhiyun /* create bound capture volume and switch controls */
create_bind_cap_vol_ctl(struct hda_codec * codec,int idx,unsigned int vol_ctl,unsigned int sw_ctl)3674*4882a593Smuzhiyun static int create_bind_cap_vol_ctl(struct hda_codec *codec, int idx,
3675*4882a593Smuzhiyun 				   unsigned int vol_ctl, unsigned int sw_ctl)
3676*4882a593Smuzhiyun {
3677*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3678*4882a593Smuzhiyun 	struct snd_kcontrol_new *knew;
3679*4882a593Smuzhiyun 
3680*4882a593Smuzhiyun 	if (vol_ctl) {
3681*4882a593Smuzhiyun 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_vol_temp);
3682*4882a593Smuzhiyun 		if (!knew)
3683*4882a593Smuzhiyun 			return -ENOMEM;
3684*4882a593Smuzhiyun 		knew->index = idx;
3685*4882a593Smuzhiyun 		knew->private_value = vol_ctl;
3686*4882a593Smuzhiyun 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3687*4882a593Smuzhiyun 	}
3688*4882a593Smuzhiyun 	if (sw_ctl) {
3689*4882a593Smuzhiyun 		knew = snd_hda_gen_add_kctl(spec, NULL, &cap_sw_temp);
3690*4882a593Smuzhiyun 		if (!knew)
3691*4882a593Smuzhiyun 			return -ENOMEM;
3692*4882a593Smuzhiyun 		knew->index = idx;
3693*4882a593Smuzhiyun 		knew->private_value = sw_ctl;
3694*4882a593Smuzhiyun 		knew->subdevice = HDA_SUBDEV_AMP_FLAG;
3695*4882a593Smuzhiyun 	}
3696*4882a593Smuzhiyun 	return 0;
3697*4882a593Smuzhiyun }
3698*4882a593Smuzhiyun 
3699*4882a593Smuzhiyun /* return the vol ctl when used first in the imux list */
get_first_cap_ctl(struct hda_codec * codec,int idx,int type)3700*4882a593Smuzhiyun static unsigned int get_first_cap_ctl(struct hda_codec *codec, int idx, int type)
3701*4882a593Smuzhiyun {
3702*4882a593Smuzhiyun 	struct nid_path *path;
3703*4882a593Smuzhiyun 	unsigned int ctl;
3704*4882a593Smuzhiyun 	int i;
3705*4882a593Smuzhiyun 
3706*4882a593Smuzhiyun 	path = get_input_path(codec, 0, idx);
3707*4882a593Smuzhiyun 	if (!path)
3708*4882a593Smuzhiyun 		return 0;
3709*4882a593Smuzhiyun 	ctl = path->ctls[type];
3710*4882a593Smuzhiyun 	if (!ctl)
3711*4882a593Smuzhiyun 		return 0;
3712*4882a593Smuzhiyun 	for (i = 0; i < idx - 1; i++) {
3713*4882a593Smuzhiyun 		path = get_input_path(codec, 0, i);
3714*4882a593Smuzhiyun 		if (path && path->ctls[type] == ctl)
3715*4882a593Smuzhiyun 			return 0;
3716*4882a593Smuzhiyun 	}
3717*4882a593Smuzhiyun 	return ctl;
3718*4882a593Smuzhiyun }
3719*4882a593Smuzhiyun 
3720*4882a593Smuzhiyun /* create individual capture volume and switch controls per input */
create_multi_cap_vol_ctl(struct hda_codec * codec)3721*4882a593Smuzhiyun static int create_multi_cap_vol_ctl(struct hda_codec *codec)
3722*4882a593Smuzhiyun {
3723*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3724*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
3725*4882a593Smuzhiyun 	int i, err, type;
3726*4882a593Smuzhiyun 
3727*4882a593Smuzhiyun 	for (i = 0; i < imux->num_items; i++) {
3728*4882a593Smuzhiyun 		bool inv_dmic;
3729*4882a593Smuzhiyun 		int idx;
3730*4882a593Smuzhiyun 
3731*4882a593Smuzhiyun 		idx = imux->items[i].index;
3732*4882a593Smuzhiyun 		if (idx >= spec->autocfg.num_inputs)
3733*4882a593Smuzhiyun 			continue;
3734*4882a593Smuzhiyun 		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);
3735*4882a593Smuzhiyun 
3736*4882a593Smuzhiyun 		for (type = 0; type < 2; type++) {
3737*4882a593Smuzhiyun 			err = add_single_cap_ctl(codec,
3738*4882a593Smuzhiyun 						 spec->input_labels[idx],
3739*4882a593Smuzhiyun 						 spec->input_label_idxs[idx],
3740*4882a593Smuzhiyun 						 type,
3741*4882a593Smuzhiyun 						 get_first_cap_ctl(codec, i, type),
3742*4882a593Smuzhiyun 						 inv_dmic);
3743*4882a593Smuzhiyun 			if (err < 0)
3744*4882a593Smuzhiyun 				return err;
3745*4882a593Smuzhiyun 		}
3746*4882a593Smuzhiyun 	}
3747*4882a593Smuzhiyun 	return 0;
3748*4882a593Smuzhiyun }
3749*4882a593Smuzhiyun 
create_capture_mixers(struct hda_codec * codec)3750*4882a593Smuzhiyun static int create_capture_mixers(struct hda_codec *codec)
3751*4882a593Smuzhiyun {
3752*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3753*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
3754*4882a593Smuzhiyun 	int i, n, nums, err;
3755*4882a593Smuzhiyun 
3756*4882a593Smuzhiyun 	if (spec->dyn_adc_switch)
3757*4882a593Smuzhiyun 		nums = 1;
3758*4882a593Smuzhiyun 	else
3759*4882a593Smuzhiyun 		nums = spec->num_adc_nids;
3760*4882a593Smuzhiyun 
3761*4882a593Smuzhiyun 	if (!spec->auto_mic && imux->num_items > 1) {
3762*4882a593Smuzhiyun 		struct snd_kcontrol_new *knew;
3763*4882a593Smuzhiyun 		const char *name;
3764*4882a593Smuzhiyun 		name = nums > 1 ? "Input Source" : "Capture Source";
3765*4882a593Smuzhiyun 		knew = snd_hda_gen_add_kctl(spec, name, &cap_src_temp);
3766*4882a593Smuzhiyun 		if (!knew)
3767*4882a593Smuzhiyun 			return -ENOMEM;
3768*4882a593Smuzhiyun 		knew->count = nums;
3769*4882a593Smuzhiyun 	}
3770*4882a593Smuzhiyun 
3771*4882a593Smuzhiyun 	for (n = 0; n < nums; n++) {
3772*4882a593Smuzhiyun 		bool multi = false;
3773*4882a593Smuzhiyun 		bool multi_cap_vol = spec->multi_cap_vol;
3774*4882a593Smuzhiyun 		bool inv_dmic = false;
3775*4882a593Smuzhiyun 		int vol, sw;
3776*4882a593Smuzhiyun 
3777*4882a593Smuzhiyun 		vol = sw = 0;
3778*4882a593Smuzhiyun 		for (i = 0; i < imux->num_items; i++) {
3779*4882a593Smuzhiyun 			struct nid_path *path;
3780*4882a593Smuzhiyun 			path = get_input_path(codec, n, i);
3781*4882a593Smuzhiyun 			if (!path)
3782*4882a593Smuzhiyun 				continue;
3783*4882a593Smuzhiyun 			parse_capvol_in_path(codec, path);
3784*4882a593Smuzhiyun 			if (!vol)
3785*4882a593Smuzhiyun 				vol = path->ctls[NID_PATH_VOL_CTL];
3786*4882a593Smuzhiyun 			else if (vol != path->ctls[NID_PATH_VOL_CTL]) {
3787*4882a593Smuzhiyun 				multi = true;
3788*4882a593Smuzhiyun 				if (!same_amp_caps(codec, vol,
3789*4882a593Smuzhiyun 				    path->ctls[NID_PATH_VOL_CTL], HDA_INPUT))
3790*4882a593Smuzhiyun 					multi_cap_vol = true;
3791*4882a593Smuzhiyun 			}
3792*4882a593Smuzhiyun 			if (!sw)
3793*4882a593Smuzhiyun 				sw = path->ctls[NID_PATH_MUTE_CTL];
3794*4882a593Smuzhiyun 			else if (sw != path->ctls[NID_PATH_MUTE_CTL]) {
3795*4882a593Smuzhiyun 				multi = true;
3796*4882a593Smuzhiyun 				if (!same_amp_caps(codec, sw,
3797*4882a593Smuzhiyun 				    path->ctls[NID_PATH_MUTE_CTL], HDA_INPUT))
3798*4882a593Smuzhiyun 					multi_cap_vol = true;
3799*4882a593Smuzhiyun 			}
3800*4882a593Smuzhiyun 			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
3801*4882a593Smuzhiyun 				inv_dmic = true;
3802*4882a593Smuzhiyun 		}
3803*4882a593Smuzhiyun 
3804*4882a593Smuzhiyun 		if (!multi)
3805*4882a593Smuzhiyun 			err = create_single_cap_vol_ctl(codec, n, vol, sw,
3806*4882a593Smuzhiyun 							inv_dmic);
3807*4882a593Smuzhiyun 		else if (!multi_cap_vol && !inv_dmic)
3808*4882a593Smuzhiyun 			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
3809*4882a593Smuzhiyun 		else
3810*4882a593Smuzhiyun 			err = create_multi_cap_vol_ctl(codec);
3811*4882a593Smuzhiyun 		if (err < 0)
3812*4882a593Smuzhiyun 			return err;
3813*4882a593Smuzhiyun 	}
3814*4882a593Smuzhiyun 
3815*4882a593Smuzhiyun 	return 0;
3816*4882a593Smuzhiyun }
3817*4882a593Smuzhiyun 
3818*4882a593Smuzhiyun /*
3819*4882a593Smuzhiyun  * add mic boosts if needed
3820*4882a593Smuzhiyun  */
3821*4882a593Smuzhiyun 
3822*4882a593Smuzhiyun /* check whether the given amp is feasible as a boost volume */
check_boost_vol(struct hda_codec * codec,hda_nid_t nid,int dir,int idx)3823*4882a593Smuzhiyun static bool check_boost_vol(struct hda_codec *codec, hda_nid_t nid,
3824*4882a593Smuzhiyun 			    int dir, int idx)
3825*4882a593Smuzhiyun {
3826*4882a593Smuzhiyun 	unsigned int step;
3827*4882a593Smuzhiyun 
3828*4882a593Smuzhiyun 	if (!nid_has_volume(codec, nid, dir) ||
3829*4882a593Smuzhiyun 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_VOL_CTL) ||
3830*4882a593Smuzhiyun 	    is_ctl_associated(codec, nid, dir, idx, NID_PATH_BOOST_CTL))
3831*4882a593Smuzhiyun 		return false;
3832*4882a593Smuzhiyun 
3833*4882a593Smuzhiyun 	step = (query_amp_caps(codec, nid, dir) & AC_AMPCAP_STEP_SIZE)
3834*4882a593Smuzhiyun 		>> AC_AMPCAP_STEP_SIZE_SHIFT;
3835*4882a593Smuzhiyun 	if (step < 0x20)
3836*4882a593Smuzhiyun 		return false;
3837*4882a593Smuzhiyun 	return true;
3838*4882a593Smuzhiyun }
3839*4882a593Smuzhiyun 
3840*4882a593Smuzhiyun /* look for a boost amp in a widget close to the pin */
look_for_boost_amp(struct hda_codec * codec,struct nid_path * path)3841*4882a593Smuzhiyun static unsigned int look_for_boost_amp(struct hda_codec *codec,
3842*4882a593Smuzhiyun 				       struct nid_path *path)
3843*4882a593Smuzhiyun {
3844*4882a593Smuzhiyun 	unsigned int val = 0;
3845*4882a593Smuzhiyun 	hda_nid_t nid;
3846*4882a593Smuzhiyun 	int depth;
3847*4882a593Smuzhiyun 
3848*4882a593Smuzhiyun 	for (depth = 0; depth < 3; depth++) {
3849*4882a593Smuzhiyun 		if (depth >= path->depth - 1)
3850*4882a593Smuzhiyun 			break;
3851*4882a593Smuzhiyun 		nid = path->path[depth];
3852*4882a593Smuzhiyun 		if (depth && check_boost_vol(codec, nid, HDA_OUTPUT, 0)) {
3853*4882a593Smuzhiyun 			val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
3854*4882a593Smuzhiyun 			break;
3855*4882a593Smuzhiyun 		} else if (check_boost_vol(codec, nid, HDA_INPUT,
3856*4882a593Smuzhiyun 					   path->idx[depth])) {
3857*4882a593Smuzhiyun 			val = HDA_COMPOSE_AMP_VAL(nid, 3, path->idx[depth],
3858*4882a593Smuzhiyun 						  HDA_INPUT);
3859*4882a593Smuzhiyun 			break;
3860*4882a593Smuzhiyun 		}
3861*4882a593Smuzhiyun 	}
3862*4882a593Smuzhiyun 
3863*4882a593Smuzhiyun 	return val;
3864*4882a593Smuzhiyun }
3865*4882a593Smuzhiyun 
parse_mic_boost(struct hda_codec * codec)3866*4882a593Smuzhiyun static int parse_mic_boost(struct hda_codec *codec)
3867*4882a593Smuzhiyun {
3868*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3869*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
3870*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
3871*4882a593Smuzhiyun 	int i;
3872*4882a593Smuzhiyun 
3873*4882a593Smuzhiyun 	if (!spec->num_adc_nids)
3874*4882a593Smuzhiyun 		return 0;
3875*4882a593Smuzhiyun 
3876*4882a593Smuzhiyun 	for (i = 0; i < imux->num_items; i++) {
3877*4882a593Smuzhiyun 		struct nid_path *path;
3878*4882a593Smuzhiyun 		unsigned int val;
3879*4882a593Smuzhiyun 		int idx;
3880*4882a593Smuzhiyun 		char boost_label[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
3881*4882a593Smuzhiyun 
3882*4882a593Smuzhiyun 		idx = imux->items[i].index;
3883*4882a593Smuzhiyun 		if (idx >= imux->num_items)
3884*4882a593Smuzhiyun 			continue;
3885*4882a593Smuzhiyun 
3886*4882a593Smuzhiyun 		/* check only line-in and mic pins */
3887*4882a593Smuzhiyun 		if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN)
3888*4882a593Smuzhiyun 			continue;
3889*4882a593Smuzhiyun 
3890*4882a593Smuzhiyun 		path = get_input_path(codec, 0, i);
3891*4882a593Smuzhiyun 		if (!path)
3892*4882a593Smuzhiyun 			continue;
3893*4882a593Smuzhiyun 
3894*4882a593Smuzhiyun 		val = look_for_boost_amp(codec, path);
3895*4882a593Smuzhiyun 		if (!val)
3896*4882a593Smuzhiyun 			continue;
3897*4882a593Smuzhiyun 
3898*4882a593Smuzhiyun 		/* create a boost control */
3899*4882a593Smuzhiyun 		snprintf(boost_label, sizeof(boost_label),
3900*4882a593Smuzhiyun 			 "%s Boost Volume", spec->input_labels[idx]);
3901*4882a593Smuzhiyun 		if (!add_control(spec, HDA_CTL_WIDGET_VOL, boost_label,
3902*4882a593Smuzhiyun 				 spec->input_label_idxs[idx], val))
3903*4882a593Smuzhiyun 			return -ENOMEM;
3904*4882a593Smuzhiyun 
3905*4882a593Smuzhiyun 		path->ctls[NID_PATH_BOOST_CTL] = val;
3906*4882a593Smuzhiyun 	}
3907*4882a593Smuzhiyun 	return 0;
3908*4882a593Smuzhiyun }
3909*4882a593Smuzhiyun 
3910*4882a593Smuzhiyun #ifdef CONFIG_SND_HDA_GENERIC_LEDS
3911*4882a593Smuzhiyun /*
3912*4882a593Smuzhiyun  * vmaster mute LED hook helpers
3913*4882a593Smuzhiyun  */
3914*4882a593Smuzhiyun 
create_mute_led_cdev(struct hda_codec * codec,int (* callback)(struct led_classdev *,enum led_brightness),bool micmute)3915*4882a593Smuzhiyun static int create_mute_led_cdev(struct hda_codec *codec,
3916*4882a593Smuzhiyun 				int (*callback)(struct led_classdev *,
3917*4882a593Smuzhiyun 						enum led_brightness),
3918*4882a593Smuzhiyun 				bool micmute)
3919*4882a593Smuzhiyun {
3920*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3921*4882a593Smuzhiyun 	struct led_classdev *cdev;
3922*4882a593Smuzhiyun 	int idx = micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE;
3923*4882a593Smuzhiyun 	int err;
3924*4882a593Smuzhiyun 
3925*4882a593Smuzhiyun 	cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
3926*4882a593Smuzhiyun 	if (!cdev)
3927*4882a593Smuzhiyun 		return -ENOMEM;
3928*4882a593Smuzhiyun 
3929*4882a593Smuzhiyun 	cdev->name = micmute ? "hda::micmute" : "hda::mute";
3930*4882a593Smuzhiyun 	cdev->max_brightness = 1;
3931*4882a593Smuzhiyun 	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
3932*4882a593Smuzhiyun 	cdev->brightness_set_blocking = callback;
3933*4882a593Smuzhiyun 	cdev->brightness = ledtrig_audio_get(idx);
3934*4882a593Smuzhiyun 	cdev->flags = LED_CORE_SUSPENDRESUME;
3935*4882a593Smuzhiyun 
3936*4882a593Smuzhiyun 	err = led_classdev_register(&codec->core.dev, cdev);
3937*4882a593Smuzhiyun 	if (err < 0)
3938*4882a593Smuzhiyun 		return err;
3939*4882a593Smuzhiyun 	spec->led_cdevs[idx] = cdev;
3940*4882a593Smuzhiyun 	return 0;
3941*4882a593Smuzhiyun }
3942*4882a593Smuzhiyun 
vmaster_update_mute_led(void * private_data,int enabled)3943*4882a593Smuzhiyun static void vmaster_update_mute_led(void *private_data, int enabled)
3944*4882a593Smuzhiyun {
3945*4882a593Smuzhiyun 	ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
3946*4882a593Smuzhiyun }
3947*4882a593Smuzhiyun 
3948*4882a593Smuzhiyun /**
3949*4882a593Smuzhiyun  * snd_dha_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
3950*4882a593Smuzhiyun  * @codec: the HDA codec
3951*4882a593Smuzhiyun  * @callback: the callback for LED classdev brightness_set_blocking
3952*4882a593Smuzhiyun  */
snd_hda_gen_add_mute_led_cdev(struct hda_codec * codec,int (* callback)(struct led_classdev *,enum led_brightness))3953*4882a593Smuzhiyun int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
3954*4882a593Smuzhiyun 				  int (*callback)(struct led_classdev *,
3955*4882a593Smuzhiyun 						  enum led_brightness))
3956*4882a593Smuzhiyun {
3957*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3958*4882a593Smuzhiyun 	int err;
3959*4882a593Smuzhiyun 
3960*4882a593Smuzhiyun 	if (callback) {
3961*4882a593Smuzhiyun 		err = create_mute_led_cdev(codec, callback, false);
3962*4882a593Smuzhiyun 		if (err) {
3963*4882a593Smuzhiyun 			codec_warn(codec, "failed to create a mute LED cdev\n");
3964*4882a593Smuzhiyun 			return err;
3965*4882a593Smuzhiyun 		}
3966*4882a593Smuzhiyun 	}
3967*4882a593Smuzhiyun 
3968*4882a593Smuzhiyun 	if (spec->vmaster_mute.hook)
3969*4882a593Smuzhiyun 		codec_err(codec, "vmaster hook already present before cdev!\n");
3970*4882a593Smuzhiyun 
3971*4882a593Smuzhiyun 	spec->vmaster_mute.hook = vmaster_update_mute_led;
3972*4882a593Smuzhiyun 	spec->vmaster_mute_enum = 1;
3973*4882a593Smuzhiyun 	return 0;
3974*4882a593Smuzhiyun }
3975*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
3976*4882a593Smuzhiyun 
3977*4882a593Smuzhiyun /*
3978*4882a593Smuzhiyun  * mic mute LED hook helpers
3979*4882a593Smuzhiyun  */
3980*4882a593Smuzhiyun enum {
3981*4882a593Smuzhiyun 	MICMUTE_LED_ON,
3982*4882a593Smuzhiyun 	MICMUTE_LED_OFF,
3983*4882a593Smuzhiyun 	MICMUTE_LED_FOLLOW_CAPTURE,
3984*4882a593Smuzhiyun 	MICMUTE_LED_FOLLOW_MUTE,
3985*4882a593Smuzhiyun };
3986*4882a593Smuzhiyun 
call_micmute_led_update(struct hda_codec * codec)3987*4882a593Smuzhiyun static void call_micmute_led_update(struct hda_codec *codec)
3988*4882a593Smuzhiyun {
3989*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
3990*4882a593Smuzhiyun 	unsigned int val;
3991*4882a593Smuzhiyun 
3992*4882a593Smuzhiyun 	switch (spec->micmute_led.led_mode) {
3993*4882a593Smuzhiyun 	case MICMUTE_LED_ON:
3994*4882a593Smuzhiyun 		val = 1;
3995*4882a593Smuzhiyun 		break;
3996*4882a593Smuzhiyun 	case MICMUTE_LED_OFF:
3997*4882a593Smuzhiyun 		val = 0;
3998*4882a593Smuzhiyun 		break;
3999*4882a593Smuzhiyun 	case MICMUTE_LED_FOLLOW_CAPTURE:
4000*4882a593Smuzhiyun 		val = !!spec->micmute_led.capture;
4001*4882a593Smuzhiyun 		break;
4002*4882a593Smuzhiyun 	case MICMUTE_LED_FOLLOW_MUTE:
4003*4882a593Smuzhiyun 	default:
4004*4882a593Smuzhiyun 		val = !spec->micmute_led.capture;
4005*4882a593Smuzhiyun 		break;
4006*4882a593Smuzhiyun 	}
4007*4882a593Smuzhiyun 
4008*4882a593Smuzhiyun 	if (val == spec->micmute_led.led_value)
4009*4882a593Smuzhiyun 		return;
4010*4882a593Smuzhiyun 	spec->micmute_led.led_value = val;
4011*4882a593Smuzhiyun 	ledtrig_audio_set(LED_AUDIO_MICMUTE,
4012*4882a593Smuzhiyun 			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
4013*4882a593Smuzhiyun }
4014*4882a593Smuzhiyun 
update_micmute_led(struct hda_codec * codec,struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4015*4882a593Smuzhiyun static void update_micmute_led(struct hda_codec *codec,
4016*4882a593Smuzhiyun 			       struct snd_kcontrol *kcontrol,
4017*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
4018*4882a593Smuzhiyun {
4019*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4020*4882a593Smuzhiyun 	unsigned int mask;
4021*4882a593Smuzhiyun 
4022*4882a593Smuzhiyun 	if (spec->micmute_led.old_hook)
4023*4882a593Smuzhiyun 		spec->micmute_led.old_hook(codec, kcontrol, ucontrol);
4024*4882a593Smuzhiyun 
4025*4882a593Smuzhiyun 	if (!ucontrol)
4026*4882a593Smuzhiyun 		return;
4027*4882a593Smuzhiyun 	mask = 1U << snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
4028*4882a593Smuzhiyun 	if (!strcmp("Capture Switch", ucontrol->id.name)) {
4029*4882a593Smuzhiyun 		/* TODO: How do I verify if it's a mono or stereo here? */
4030*4882a593Smuzhiyun 		if (ucontrol->value.integer.value[0] ||
4031*4882a593Smuzhiyun 		    ucontrol->value.integer.value[1])
4032*4882a593Smuzhiyun 			spec->micmute_led.capture |= mask;
4033*4882a593Smuzhiyun 		else
4034*4882a593Smuzhiyun 			spec->micmute_led.capture &= ~mask;
4035*4882a593Smuzhiyun 		call_micmute_led_update(codec);
4036*4882a593Smuzhiyun 	}
4037*4882a593Smuzhiyun }
4038*4882a593Smuzhiyun 
micmute_led_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)4039*4882a593Smuzhiyun static int micmute_led_mode_info(struct snd_kcontrol *kcontrol,
4040*4882a593Smuzhiyun 				 struct snd_ctl_elem_info *uinfo)
4041*4882a593Smuzhiyun {
4042*4882a593Smuzhiyun 	static const char * const texts[] = {
4043*4882a593Smuzhiyun 		"On", "Off", "Follow Capture", "Follow Mute",
4044*4882a593Smuzhiyun 	};
4045*4882a593Smuzhiyun 
4046*4882a593Smuzhiyun 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
4047*4882a593Smuzhiyun }
4048*4882a593Smuzhiyun 
micmute_led_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4049*4882a593Smuzhiyun static int micmute_led_mode_get(struct snd_kcontrol *kcontrol,
4050*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
4051*4882a593Smuzhiyun {
4052*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4053*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4054*4882a593Smuzhiyun 
4055*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = spec->micmute_led.led_mode;
4056*4882a593Smuzhiyun 	return 0;
4057*4882a593Smuzhiyun }
4058*4882a593Smuzhiyun 
micmute_led_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4059*4882a593Smuzhiyun static int micmute_led_mode_put(struct snd_kcontrol *kcontrol,
4060*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
4061*4882a593Smuzhiyun {
4062*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4063*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4064*4882a593Smuzhiyun 	unsigned int mode;
4065*4882a593Smuzhiyun 
4066*4882a593Smuzhiyun 	mode = ucontrol->value.enumerated.item[0];
4067*4882a593Smuzhiyun 	if (mode > MICMUTE_LED_FOLLOW_MUTE)
4068*4882a593Smuzhiyun 		mode = MICMUTE_LED_FOLLOW_MUTE;
4069*4882a593Smuzhiyun 	if (mode == spec->micmute_led.led_mode)
4070*4882a593Smuzhiyun 		return 0;
4071*4882a593Smuzhiyun 	spec->micmute_led.led_mode = mode;
4072*4882a593Smuzhiyun 	call_micmute_led_update(codec);
4073*4882a593Smuzhiyun 	return 1;
4074*4882a593Smuzhiyun }
4075*4882a593Smuzhiyun 
4076*4882a593Smuzhiyun static const struct snd_kcontrol_new micmute_led_mode_ctl = {
4077*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4078*4882a593Smuzhiyun 	.name = "Mic Mute-LED Mode",
4079*4882a593Smuzhiyun 	.info = micmute_led_mode_info,
4080*4882a593Smuzhiyun 	.get = micmute_led_mode_get,
4081*4882a593Smuzhiyun 	.put = micmute_led_mode_put,
4082*4882a593Smuzhiyun };
4083*4882a593Smuzhiyun 
4084*4882a593Smuzhiyun /* Set up the capture sync hook for controlling the mic-mute LED */
add_micmute_led_hook(struct hda_codec * codec)4085*4882a593Smuzhiyun static int add_micmute_led_hook(struct hda_codec *codec)
4086*4882a593Smuzhiyun {
4087*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4088*4882a593Smuzhiyun 
4089*4882a593Smuzhiyun 	spec->micmute_led.led_mode = MICMUTE_LED_FOLLOW_MUTE;
4090*4882a593Smuzhiyun 	spec->micmute_led.capture = 0;
4091*4882a593Smuzhiyun 	spec->micmute_led.led_value = -1;
4092*4882a593Smuzhiyun 	spec->micmute_led.old_hook = spec->cap_sync_hook;
4093*4882a593Smuzhiyun 	spec->cap_sync_hook = update_micmute_led;
4094*4882a593Smuzhiyun 	if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
4095*4882a593Smuzhiyun 		return -ENOMEM;
4096*4882a593Smuzhiyun 	return 0;
4097*4882a593Smuzhiyun }
4098*4882a593Smuzhiyun 
4099*4882a593Smuzhiyun /**
4100*4882a593Smuzhiyun  * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
4101*4882a593Smuzhiyun  * @codec: the HDA codec
4102*4882a593Smuzhiyun  * @callback: the callback for LED classdev brightness_set_blocking
4103*4882a593Smuzhiyun  *
4104*4882a593Smuzhiyun  * Called from the codec drivers for offering the mic mute LED controls.
4105*4882a593Smuzhiyun  * This creates a LED classdev and sets up the cap_sync_hook that is called at
4106*4882a593Smuzhiyun  * each time when the capture mixer switch changes.
4107*4882a593Smuzhiyun  *
4108*4882a593Smuzhiyun  * When NULL is passed to @callback, no classdev is created but only the
4109*4882a593Smuzhiyun  * LED-trigger is set up.
4110*4882a593Smuzhiyun  *
4111*4882a593Smuzhiyun  * Returns 0 or a negative error.
4112*4882a593Smuzhiyun  */
snd_hda_gen_add_micmute_led_cdev(struct hda_codec * codec,int (* callback)(struct led_classdev *,enum led_brightness))4113*4882a593Smuzhiyun int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
4114*4882a593Smuzhiyun 				     int (*callback)(struct led_classdev *,
4115*4882a593Smuzhiyun 						     enum led_brightness))
4116*4882a593Smuzhiyun {
4117*4882a593Smuzhiyun 	int err;
4118*4882a593Smuzhiyun 
4119*4882a593Smuzhiyun 	if (callback) {
4120*4882a593Smuzhiyun 		err = create_mute_led_cdev(codec, callback, true);
4121*4882a593Smuzhiyun 		if (err) {
4122*4882a593Smuzhiyun 			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
4123*4882a593Smuzhiyun 			return err;
4124*4882a593Smuzhiyun 		}
4125*4882a593Smuzhiyun 	}
4126*4882a593Smuzhiyun 
4127*4882a593Smuzhiyun 	return add_micmute_led_hook(codec);
4128*4882a593Smuzhiyun }
4129*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
4130*4882a593Smuzhiyun #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
4131*4882a593Smuzhiyun 
4132*4882a593Smuzhiyun /*
4133*4882a593Smuzhiyun  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
4134*4882a593Smuzhiyun  */
parse_digital(struct hda_codec * codec)4135*4882a593Smuzhiyun static void parse_digital(struct hda_codec *codec)
4136*4882a593Smuzhiyun {
4137*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4138*4882a593Smuzhiyun 	struct nid_path *path;
4139*4882a593Smuzhiyun 	int i, nums;
4140*4882a593Smuzhiyun 	hda_nid_t dig_nid, pin;
4141*4882a593Smuzhiyun 
4142*4882a593Smuzhiyun 	/* support multiple SPDIFs; the secondary is set up as a follower */
4143*4882a593Smuzhiyun 	nums = 0;
4144*4882a593Smuzhiyun 	for (i = 0; i < spec->autocfg.dig_outs; i++) {
4145*4882a593Smuzhiyun 		pin = spec->autocfg.dig_out_pins[i];
4146*4882a593Smuzhiyun 		dig_nid = look_for_dac(codec, pin, true);
4147*4882a593Smuzhiyun 		if (!dig_nid)
4148*4882a593Smuzhiyun 			continue;
4149*4882a593Smuzhiyun 		path = snd_hda_add_new_path(codec, dig_nid, pin, 0);
4150*4882a593Smuzhiyun 		if (!path)
4151*4882a593Smuzhiyun 			continue;
4152*4882a593Smuzhiyun 		print_nid_path(codec, "digout", path);
4153*4882a593Smuzhiyun 		path->active = true;
4154*4882a593Smuzhiyun 		path->pin_fixed = true; /* no jack detection */
4155*4882a593Smuzhiyun 		spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
4156*4882a593Smuzhiyun 		set_pin_target(codec, pin, PIN_OUT, false);
4157*4882a593Smuzhiyun 		if (!nums) {
4158*4882a593Smuzhiyun 			spec->multiout.dig_out_nid = dig_nid;
4159*4882a593Smuzhiyun 			spec->dig_out_type = spec->autocfg.dig_out_type[0];
4160*4882a593Smuzhiyun 		} else {
4161*4882a593Smuzhiyun 			spec->multiout.follower_dig_outs = spec->follower_dig_outs;
4162*4882a593Smuzhiyun 			if (nums >= ARRAY_SIZE(spec->follower_dig_outs) - 1)
4163*4882a593Smuzhiyun 				break;
4164*4882a593Smuzhiyun 			spec->follower_dig_outs[nums - 1] = dig_nid;
4165*4882a593Smuzhiyun 		}
4166*4882a593Smuzhiyun 		nums++;
4167*4882a593Smuzhiyun 	}
4168*4882a593Smuzhiyun 
4169*4882a593Smuzhiyun 	if (spec->autocfg.dig_in_pin) {
4170*4882a593Smuzhiyun 		pin = spec->autocfg.dig_in_pin;
4171*4882a593Smuzhiyun 		for_each_hda_codec_node(dig_nid, codec) {
4172*4882a593Smuzhiyun 			unsigned int wcaps = get_wcaps(codec, dig_nid);
4173*4882a593Smuzhiyun 			if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
4174*4882a593Smuzhiyun 				continue;
4175*4882a593Smuzhiyun 			if (!(wcaps & AC_WCAP_DIGITAL))
4176*4882a593Smuzhiyun 				continue;
4177*4882a593Smuzhiyun 			path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
4178*4882a593Smuzhiyun 			if (path) {
4179*4882a593Smuzhiyun 				print_nid_path(codec, "digin", path);
4180*4882a593Smuzhiyun 				path->active = true;
4181*4882a593Smuzhiyun 				path->pin_fixed = true; /* no jack */
4182*4882a593Smuzhiyun 				spec->dig_in_nid = dig_nid;
4183*4882a593Smuzhiyun 				spec->digin_path = snd_hda_get_path_idx(codec, path);
4184*4882a593Smuzhiyun 				set_pin_target(codec, pin, PIN_IN, false);
4185*4882a593Smuzhiyun 				break;
4186*4882a593Smuzhiyun 			}
4187*4882a593Smuzhiyun 		}
4188*4882a593Smuzhiyun 	}
4189*4882a593Smuzhiyun }
4190*4882a593Smuzhiyun 
4191*4882a593Smuzhiyun 
4192*4882a593Smuzhiyun /*
4193*4882a593Smuzhiyun  * input MUX handling
4194*4882a593Smuzhiyun  */
4195*4882a593Smuzhiyun 
4196*4882a593Smuzhiyun static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur);
4197*4882a593Smuzhiyun 
4198*4882a593Smuzhiyun /* select the given imux item; either unmute exclusively or select the route */
mux_select(struct hda_codec * codec,unsigned int adc_idx,unsigned int idx)4199*4882a593Smuzhiyun static int mux_select(struct hda_codec *codec, unsigned int adc_idx,
4200*4882a593Smuzhiyun 		      unsigned int idx)
4201*4882a593Smuzhiyun {
4202*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4203*4882a593Smuzhiyun 	const struct hda_input_mux *imux;
4204*4882a593Smuzhiyun 	struct nid_path *old_path, *path;
4205*4882a593Smuzhiyun 
4206*4882a593Smuzhiyun 	imux = &spec->input_mux;
4207*4882a593Smuzhiyun 	if (!imux->num_items)
4208*4882a593Smuzhiyun 		return 0;
4209*4882a593Smuzhiyun 
4210*4882a593Smuzhiyun 	if (idx >= imux->num_items)
4211*4882a593Smuzhiyun 		idx = imux->num_items - 1;
4212*4882a593Smuzhiyun 	if (spec->cur_mux[adc_idx] == idx)
4213*4882a593Smuzhiyun 		return 0;
4214*4882a593Smuzhiyun 
4215*4882a593Smuzhiyun 	old_path = get_input_path(codec, adc_idx, spec->cur_mux[adc_idx]);
4216*4882a593Smuzhiyun 	if (!old_path)
4217*4882a593Smuzhiyun 		return 0;
4218*4882a593Smuzhiyun 	if (old_path->active)
4219*4882a593Smuzhiyun 		snd_hda_activate_path(codec, old_path, false, false);
4220*4882a593Smuzhiyun 
4221*4882a593Smuzhiyun 	spec->cur_mux[adc_idx] = idx;
4222*4882a593Smuzhiyun 
4223*4882a593Smuzhiyun 	if (spec->hp_mic)
4224*4882a593Smuzhiyun 		update_hp_mic(codec, adc_idx, false);
4225*4882a593Smuzhiyun 
4226*4882a593Smuzhiyun 	if (spec->dyn_adc_switch)
4227*4882a593Smuzhiyun 		dyn_adc_pcm_resetup(codec, idx);
4228*4882a593Smuzhiyun 
4229*4882a593Smuzhiyun 	path = get_input_path(codec, adc_idx, idx);
4230*4882a593Smuzhiyun 	if (!path)
4231*4882a593Smuzhiyun 		return 0;
4232*4882a593Smuzhiyun 	if (path->active)
4233*4882a593Smuzhiyun 		return 0;
4234*4882a593Smuzhiyun 	snd_hda_activate_path(codec, path, true, false);
4235*4882a593Smuzhiyun 	if (spec->cap_sync_hook)
4236*4882a593Smuzhiyun 		spec->cap_sync_hook(codec, NULL, NULL);
4237*4882a593Smuzhiyun 	path_power_down_sync(codec, old_path);
4238*4882a593Smuzhiyun 	return 1;
4239*4882a593Smuzhiyun }
4240*4882a593Smuzhiyun 
4241*4882a593Smuzhiyun /* power up/down widgets in the all paths that match with the given NID
4242*4882a593Smuzhiyun  * as terminals (either start- or endpoint)
4243*4882a593Smuzhiyun  *
4244*4882a593Smuzhiyun  * returns the last changed NID, or zero if unchanged.
4245*4882a593Smuzhiyun  */
set_path_power(struct hda_codec * codec,hda_nid_t nid,int pin_state,int stream_state)4246*4882a593Smuzhiyun static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
4247*4882a593Smuzhiyun 				int pin_state, int stream_state)
4248*4882a593Smuzhiyun {
4249*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4250*4882a593Smuzhiyun 	hda_nid_t last, changed = 0;
4251*4882a593Smuzhiyun 	struct nid_path *path;
4252*4882a593Smuzhiyun 	int n;
4253*4882a593Smuzhiyun 
4254*4882a593Smuzhiyun 	snd_array_for_each(&spec->paths, n, path) {
4255*4882a593Smuzhiyun 		if (!path->depth)
4256*4882a593Smuzhiyun 			continue;
4257*4882a593Smuzhiyun 		if (path->path[0] == nid ||
4258*4882a593Smuzhiyun 		    path->path[path->depth - 1] == nid) {
4259*4882a593Smuzhiyun 			bool pin_old = path->pin_enabled;
4260*4882a593Smuzhiyun 			bool stream_old = path->stream_enabled;
4261*4882a593Smuzhiyun 
4262*4882a593Smuzhiyun 			if (pin_state >= 0)
4263*4882a593Smuzhiyun 				path->pin_enabled = pin_state;
4264*4882a593Smuzhiyun 			if (stream_state >= 0)
4265*4882a593Smuzhiyun 				path->stream_enabled = stream_state;
4266*4882a593Smuzhiyun 			if ((!path->pin_fixed && path->pin_enabled != pin_old)
4267*4882a593Smuzhiyun 			    || path->stream_enabled != stream_old) {
4268*4882a593Smuzhiyun 				last = path_power_update(codec, path, true);
4269*4882a593Smuzhiyun 				if (last)
4270*4882a593Smuzhiyun 					changed = last;
4271*4882a593Smuzhiyun 			}
4272*4882a593Smuzhiyun 		}
4273*4882a593Smuzhiyun 	}
4274*4882a593Smuzhiyun 	return changed;
4275*4882a593Smuzhiyun }
4276*4882a593Smuzhiyun 
4277*4882a593Smuzhiyun /* check the jack status for power control */
detect_pin_state(struct hda_codec * codec,hda_nid_t pin)4278*4882a593Smuzhiyun static bool detect_pin_state(struct hda_codec *codec, hda_nid_t pin)
4279*4882a593Smuzhiyun {
4280*4882a593Smuzhiyun 	if (!is_jack_detectable(codec, pin))
4281*4882a593Smuzhiyun 		return true;
4282*4882a593Smuzhiyun 	return snd_hda_jack_detect_state(codec, pin) != HDA_JACK_NOT_PRESENT;
4283*4882a593Smuzhiyun }
4284*4882a593Smuzhiyun 
4285*4882a593Smuzhiyun /* power up/down the paths of the given pin according to the jack state;
4286*4882a593Smuzhiyun  * power = 0/1 : only power up/down if it matches with the jack state,
4287*4882a593Smuzhiyun  *       < 0   : force power up/down to follow the jack sate
4288*4882a593Smuzhiyun  *
4289*4882a593Smuzhiyun  * returns the last changed NID, or zero if unchanged.
4290*4882a593Smuzhiyun  */
set_pin_power_jack(struct hda_codec * codec,hda_nid_t pin,int power)4291*4882a593Smuzhiyun static hda_nid_t set_pin_power_jack(struct hda_codec *codec, hda_nid_t pin,
4292*4882a593Smuzhiyun 				    int power)
4293*4882a593Smuzhiyun {
4294*4882a593Smuzhiyun 	bool on;
4295*4882a593Smuzhiyun 
4296*4882a593Smuzhiyun 	if (!codec->power_save_node)
4297*4882a593Smuzhiyun 		return 0;
4298*4882a593Smuzhiyun 
4299*4882a593Smuzhiyun 	on = detect_pin_state(codec, pin);
4300*4882a593Smuzhiyun 
4301*4882a593Smuzhiyun 	if (power >= 0 && on != power)
4302*4882a593Smuzhiyun 		return 0;
4303*4882a593Smuzhiyun 	return set_path_power(codec, pin, on, -1);
4304*4882a593Smuzhiyun }
4305*4882a593Smuzhiyun 
pin_power_callback(struct hda_codec * codec,struct hda_jack_callback * jack,bool on)4306*4882a593Smuzhiyun static void pin_power_callback(struct hda_codec *codec,
4307*4882a593Smuzhiyun 			       struct hda_jack_callback *jack,
4308*4882a593Smuzhiyun 			       bool on)
4309*4882a593Smuzhiyun {
4310*4882a593Smuzhiyun 	if (jack && jack->nid)
4311*4882a593Smuzhiyun 		sync_power_state_change(codec,
4312*4882a593Smuzhiyun 					set_pin_power_jack(codec, jack->nid, on));
4313*4882a593Smuzhiyun }
4314*4882a593Smuzhiyun 
4315*4882a593Smuzhiyun /* callback only doing power up -- called at first */
pin_power_up_callback(struct hda_codec * codec,struct hda_jack_callback * jack)4316*4882a593Smuzhiyun static void pin_power_up_callback(struct hda_codec *codec,
4317*4882a593Smuzhiyun 				  struct hda_jack_callback *jack)
4318*4882a593Smuzhiyun {
4319*4882a593Smuzhiyun 	pin_power_callback(codec, jack, true);
4320*4882a593Smuzhiyun }
4321*4882a593Smuzhiyun 
4322*4882a593Smuzhiyun /* callback only doing power down -- called at last */
pin_power_down_callback(struct hda_codec * codec,struct hda_jack_callback * jack)4323*4882a593Smuzhiyun static void pin_power_down_callback(struct hda_codec *codec,
4324*4882a593Smuzhiyun 				    struct hda_jack_callback *jack)
4325*4882a593Smuzhiyun {
4326*4882a593Smuzhiyun 	pin_power_callback(codec, jack, false);
4327*4882a593Smuzhiyun }
4328*4882a593Smuzhiyun 
4329*4882a593Smuzhiyun /* set up the power up/down callbacks */
add_pin_power_ctls(struct hda_codec * codec,int num_pins,const hda_nid_t * pins,bool on)4330*4882a593Smuzhiyun static void add_pin_power_ctls(struct hda_codec *codec, int num_pins,
4331*4882a593Smuzhiyun 			       const hda_nid_t *pins, bool on)
4332*4882a593Smuzhiyun {
4333*4882a593Smuzhiyun 	int i;
4334*4882a593Smuzhiyun 	hda_jack_callback_fn cb =
4335*4882a593Smuzhiyun 		on ? pin_power_up_callback : pin_power_down_callback;
4336*4882a593Smuzhiyun 
4337*4882a593Smuzhiyun 	for (i = 0; i < num_pins && pins[i]; i++) {
4338*4882a593Smuzhiyun 		if (is_jack_detectable(codec, pins[i]))
4339*4882a593Smuzhiyun 			snd_hda_jack_detect_enable_callback(codec, pins[i], cb);
4340*4882a593Smuzhiyun 		else
4341*4882a593Smuzhiyun 			set_path_power(codec, pins[i], true, -1);
4342*4882a593Smuzhiyun 	}
4343*4882a593Smuzhiyun }
4344*4882a593Smuzhiyun 
4345*4882a593Smuzhiyun /* enabled power callback to each available I/O pin with jack detections;
4346*4882a593Smuzhiyun  * the digital I/O pins are excluded because of the unreliable detectsion
4347*4882a593Smuzhiyun  */
add_all_pin_power_ctls(struct hda_codec * codec,bool on)4348*4882a593Smuzhiyun static void add_all_pin_power_ctls(struct hda_codec *codec, bool on)
4349*4882a593Smuzhiyun {
4350*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4351*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
4352*4882a593Smuzhiyun 	int i;
4353*4882a593Smuzhiyun 
4354*4882a593Smuzhiyun 	if (!codec->power_save_node)
4355*4882a593Smuzhiyun 		return;
4356*4882a593Smuzhiyun 	add_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins, on);
4357*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4358*4882a593Smuzhiyun 		add_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins, on);
4359*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4360*4882a593Smuzhiyun 		add_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, on);
4361*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++)
4362*4882a593Smuzhiyun 		add_pin_power_ctls(codec, 1, &cfg->inputs[i].pin, on);
4363*4882a593Smuzhiyun }
4364*4882a593Smuzhiyun 
4365*4882a593Smuzhiyun /* sync path power up/down with the jack states of given pins */
sync_pin_power_ctls(struct hda_codec * codec,int num_pins,const hda_nid_t * pins)4366*4882a593Smuzhiyun static void sync_pin_power_ctls(struct hda_codec *codec, int num_pins,
4367*4882a593Smuzhiyun 				const hda_nid_t *pins)
4368*4882a593Smuzhiyun {
4369*4882a593Smuzhiyun 	int i;
4370*4882a593Smuzhiyun 
4371*4882a593Smuzhiyun 	for (i = 0; i < num_pins && pins[i]; i++)
4372*4882a593Smuzhiyun 		if (is_jack_detectable(codec, pins[i]))
4373*4882a593Smuzhiyun 			set_pin_power_jack(codec, pins[i], -1);
4374*4882a593Smuzhiyun }
4375*4882a593Smuzhiyun 
4376*4882a593Smuzhiyun /* sync path power up/down with pins; called at init and resume */
sync_all_pin_power_ctls(struct hda_codec * codec)4377*4882a593Smuzhiyun static void sync_all_pin_power_ctls(struct hda_codec *codec)
4378*4882a593Smuzhiyun {
4379*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4380*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
4381*4882a593Smuzhiyun 	int i;
4382*4882a593Smuzhiyun 
4383*4882a593Smuzhiyun 	if (!codec->power_save_node)
4384*4882a593Smuzhiyun 		return;
4385*4882a593Smuzhiyun 	sync_pin_power_ctls(codec, cfg->line_outs, cfg->line_out_pins);
4386*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
4387*4882a593Smuzhiyun 		sync_pin_power_ctls(codec, cfg->hp_outs, cfg->hp_pins);
4388*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
4389*4882a593Smuzhiyun 		sync_pin_power_ctls(codec, cfg->speaker_outs, cfg->speaker_pins);
4390*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++)
4391*4882a593Smuzhiyun 		sync_pin_power_ctls(codec, 1, &cfg->inputs[i].pin);
4392*4882a593Smuzhiyun }
4393*4882a593Smuzhiyun 
4394*4882a593Smuzhiyun /* add fake paths if not present yet */
add_fake_paths(struct hda_codec * codec,hda_nid_t nid,int num_pins,const hda_nid_t * pins)4395*4882a593Smuzhiyun static int add_fake_paths(struct hda_codec *codec, hda_nid_t nid,
4396*4882a593Smuzhiyun 			   int num_pins, const hda_nid_t *pins)
4397*4882a593Smuzhiyun {
4398*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4399*4882a593Smuzhiyun 	struct nid_path *path;
4400*4882a593Smuzhiyun 	int i;
4401*4882a593Smuzhiyun 
4402*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++) {
4403*4882a593Smuzhiyun 		if (!pins[i])
4404*4882a593Smuzhiyun 			break;
4405*4882a593Smuzhiyun 		if (get_nid_path(codec, nid, pins[i], 0))
4406*4882a593Smuzhiyun 			continue;
4407*4882a593Smuzhiyun 		path = snd_array_new(&spec->paths);
4408*4882a593Smuzhiyun 		if (!path)
4409*4882a593Smuzhiyun 			return -ENOMEM;
4410*4882a593Smuzhiyun 		memset(path, 0, sizeof(*path));
4411*4882a593Smuzhiyun 		path->depth = 2;
4412*4882a593Smuzhiyun 		path->path[0] = nid;
4413*4882a593Smuzhiyun 		path->path[1] = pins[i];
4414*4882a593Smuzhiyun 		path->active = true;
4415*4882a593Smuzhiyun 	}
4416*4882a593Smuzhiyun 	return 0;
4417*4882a593Smuzhiyun }
4418*4882a593Smuzhiyun 
4419*4882a593Smuzhiyun /* create fake paths to all outputs from beep */
add_fake_beep_paths(struct hda_codec * codec)4420*4882a593Smuzhiyun static int add_fake_beep_paths(struct hda_codec *codec)
4421*4882a593Smuzhiyun {
4422*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4423*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
4424*4882a593Smuzhiyun 	hda_nid_t nid = spec->beep_nid;
4425*4882a593Smuzhiyun 	int err;
4426*4882a593Smuzhiyun 
4427*4882a593Smuzhiyun 	if (!codec->power_save_node || !nid)
4428*4882a593Smuzhiyun 		return 0;
4429*4882a593Smuzhiyun 	err = add_fake_paths(codec, nid, cfg->line_outs, cfg->line_out_pins);
4430*4882a593Smuzhiyun 	if (err < 0)
4431*4882a593Smuzhiyun 		return err;
4432*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
4433*4882a593Smuzhiyun 		err = add_fake_paths(codec, nid, cfg->hp_outs, cfg->hp_pins);
4434*4882a593Smuzhiyun 		if (err < 0)
4435*4882a593Smuzhiyun 			return err;
4436*4882a593Smuzhiyun 	}
4437*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
4438*4882a593Smuzhiyun 		err = add_fake_paths(codec, nid, cfg->speaker_outs,
4439*4882a593Smuzhiyun 				     cfg->speaker_pins);
4440*4882a593Smuzhiyun 		if (err < 0)
4441*4882a593Smuzhiyun 			return err;
4442*4882a593Smuzhiyun 	}
4443*4882a593Smuzhiyun 	return 0;
4444*4882a593Smuzhiyun }
4445*4882a593Smuzhiyun 
4446*4882a593Smuzhiyun /* power up/down beep widget and its output paths */
beep_power_hook(struct hda_beep * beep,bool on)4447*4882a593Smuzhiyun static void beep_power_hook(struct hda_beep *beep, bool on)
4448*4882a593Smuzhiyun {
4449*4882a593Smuzhiyun 	set_path_power(beep->codec, beep->nid, -1, on);
4450*4882a593Smuzhiyun }
4451*4882a593Smuzhiyun 
4452*4882a593Smuzhiyun /**
4453*4882a593Smuzhiyun  * snd_hda_gen_fix_pin_power - Fix the power of the given pin widget to D0
4454*4882a593Smuzhiyun  * @codec: the HDA codec
4455*4882a593Smuzhiyun  * @pin: NID of pin to fix
4456*4882a593Smuzhiyun  */
snd_hda_gen_fix_pin_power(struct hda_codec * codec,hda_nid_t pin)4457*4882a593Smuzhiyun int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin)
4458*4882a593Smuzhiyun {
4459*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4460*4882a593Smuzhiyun 	struct nid_path *path;
4461*4882a593Smuzhiyun 
4462*4882a593Smuzhiyun 	path = snd_array_new(&spec->paths);
4463*4882a593Smuzhiyun 	if (!path)
4464*4882a593Smuzhiyun 		return -ENOMEM;
4465*4882a593Smuzhiyun 	memset(path, 0, sizeof(*path));
4466*4882a593Smuzhiyun 	path->depth = 1;
4467*4882a593Smuzhiyun 	path->path[0] = pin;
4468*4882a593Smuzhiyun 	path->active = true;
4469*4882a593Smuzhiyun 	path->pin_fixed = true;
4470*4882a593Smuzhiyun 	path->stream_enabled = true;
4471*4882a593Smuzhiyun 	return 0;
4472*4882a593Smuzhiyun }
4473*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
4474*4882a593Smuzhiyun 
4475*4882a593Smuzhiyun /*
4476*4882a593Smuzhiyun  * Jack detections for HP auto-mute and mic-switch
4477*4882a593Smuzhiyun  */
4478*4882a593Smuzhiyun 
4479*4882a593Smuzhiyun /* check each pin in the given array; returns true if any of them is plugged */
detect_jacks(struct hda_codec * codec,int num_pins,const hda_nid_t * pins)4480*4882a593Smuzhiyun static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
4481*4882a593Smuzhiyun {
4482*4882a593Smuzhiyun 	int i;
4483*4882a593Smuzhiyun 	bool present = false;
4484*4882a593Smuzhiyun 
4485*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++) {
4486*4882a593Smuzhiyun 		hda_nid_t nid = pins[i];
4487*4882a593Smuzhiyun 		if (!nid)
4488*4882a593Smuzhiyun 			break;
4489*4882a593Smuzhiyun 		/* don't detect pins retasked as inputs */
4490*4882a593Smuzhiyun 		if (snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_IN_EN)
4491*4882a593Smuzhiyun 			continue;
4492*4882a593Smuzhiyun 		if (snd_hda_jack_detect_state(codec, nid) == HDA_JACK_PRESENT)
4493*4882a593Smuzhiyun 			present = true;
4494*4882a593Smuzhiyun 	}
4495*4882a593Smuzhiyun 	return present;
4496*4882a593Smuzhiyun }
4497*4882a593Smuzhiyun 
4498*4882a593Smuzhiyun /* standard HP/line-out auto-mute helper */
do_automute(struct hda_codec * codec,int num_pins,const hda_nid_t * pins,int * paths,bool mute)4499*4882a593Smuzhiyun static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
4500*4882a593Smuzhiyun 			int *paths, bool mute)
4501*4882a593Smuzhiyun {
4502*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4503*4882a593Smuzhiyun 	int i;
4504*4882a593Smuzhiyun 
4505*4882a593Smuzhiyun 	for (i = 0; i < num_pins; i++) {
4506*4882a593Smuzhiyun 		hda_nid_t nid = pins[i];
4507*4882a593Smuzhiyun 		unsigned int val, oldval;
4508*4882a593Smuzhiyun 		if (!nid)
4509*4882a593Smuzhiyun 			break;
4510*4882a593Smuzhiyun 
4511*4882a593Smuzhiyun 		oldval = snd_hda_codec_get_pin_target(codec, nid);
4512*4882a593Smuzhiyun 		if (oldval & PIN_IN)
4513*4882a593Smuzhiyun 			continue; /* no mute for inputs */
4514*4882a593Smuzhiyun 
4515*4882a593Smuzhiyun 		if (spec->auto_mute_via_amp) {
4516*4882a593Smuzhiyun 			struct nid_path *path;
4517*4882a593Smuzhiyun 			hda_nid_t mute_nid;
4518*4882a593Smuzhiyun 
4519*4882a593Smuzhiyun 			path = snd_hda_get_path_from_idx(codec, paths[i]);
4520*4882a593Smuzhiyun 			if (!path)
4521*4882a593Smuzhiyun 				continue;
4522*4882a593Smuzhiyun 			mute_nid = get_amp_nid_(path->ctls[NID_PATH_MUTE_CTL]);
4523*4882a593Smuzhiyun 			if (!mute_nid)
4524*4882a593Smuzhiyun 				continue;
4525*4882a593Smuzhiyun 			if (mute)
4526*4882a593Smuzhiyun 				spec->mute_bits |= (1ULL << mute_nid);
4527*4882a593Smuzhiyun 			else
4528*4882a593Smuzhiyun 				spec->mute_bits &= ~(1ULL << mute_nid);
4529*4882a593Smuzhiyun 			continue;
4530*4882a593Smuzhiyun 		} else {
4531*4882a593Smuzhiyun 			/* don't reset VREF value in case it's controlling
4532*4882a593Smuzhiyun 			 * the amp (see alc861_fixup_asus_amp_vref_0f())
4533*4882a593Smuzhiyun 			 */
4534*4882a593Smuzhiyun 			if (spec->keep_vref_in_automute)
4535*4882a593Smuzhiyun 				val = oldval & ~PIN_HP;
4536*4882a593Smuzhiyun 			else
4537*4882a593Smuzhiyun 				val = 0;
4538*4882a593Smuzhiyun 			if (!mute)
4539*4882a593Smuzhiyun 				val |= oldval;
4540*4882a593Smuzhiyun 			/* here we call update_pin_ctl() so that the pinctl is
4541*4882a593Smuzhiyun 			 * changed without changing the pinctl target value;
4542*4882a593Smuzhiyun 			 * the original target value will be still referred at
4543*4882a593Smuzhiyun 			 * the init / resume again
4544*4882a593Smuzhiyun 			 */
4545*4882a593Smuzhiyun 			update_pin_ctl(codec, nid, val);
4546*4882a593Smuzhiyun 		}
4547*4882a593Smuzhiyun 
4548*4882a593Smuzhiyun 		set_pin_eapd(codec, nid, !mute);
4549*4882a593Smuzhiyun 		if (codec->power_save_node) {
4550*4882a593Smuzhiyun 			bool on = !mute;
4551*4882a593Smuzhiyun 			if (on)
4552*4882a593Smuzhiyun 				on = detect_pin_state(codec, nid);
4553*4882a593Smuzhiyun 			set_path_power(codec, nid, on, -1);
4554*4882a593Smuzhiyun 		}
4555*4882a593Smuzhiyun 	}
4556*4882a593Smuzhiyun }
4557*4882a593Smuzhiyun 
4558*4882a593Smuzhiyun /**
4559*4882a593Smuzhiyun  * snd_hda_gen_update_outputs - Toggle outputs muting
4560*4882a593Smuzhiyun  * @codec: the HDA codec
4561*4882a593Smuzhiyun  *
4562*4882a593Smuzhiyun  * Update the mute status of all outputs based on the current jack states.
4563*4882a593Smuzhiyun  */
snd_hda_gen_update_outputs(struct hda_codec * codec)4564*4882a593Smuzhiyun void snd_hda_gen_update_outputs(struct hda_codec *codec)
4565*4882a593Smuzhiyun {
4566*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4567*4882a593Smuzhiyun 	int *paths;
4568*4882a593Smuzhiyun 	int on;
4569*4882a593Smuzhiyun 
4570*4882a593Smuzhiyun 	/* Control HP pins/amps depending on master_mute state;
4571*4882a593Smuzhiyun 	 * in general, HP pins/amps control should be enabled in all cases,
4572*4882a593Smuzhiyun 	 * but currently set only for master_mute, just to be safe
4573*4882a593Smuzhiyun 	 */
4574*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
4575*4882a593Smuzhiyun 		paths = spec->out_paths;
4576*4882a593Smuzhiyun 	else
4577*4882a593Smuzhiyun 		paths = spec->hp_paths;
4578*4882a593Smuzhiyun 	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
4579*4882a593Smuzhiyun 		    spec->autocfg.hp_pins, paths, spec->master_mute);
4580*4882a593Smuzhiyun 
4581*4882a593Smuzhiyun 	if (!spec->automute_speaker)
4582*4882a593Smuzhiyun 		on = 0;
4583*4882a593Smuzhiyun 	else
4584*4882a593Smuzhiyun 		on = spec->hp_jack_present | spec->line_jack_present;
4585*4882a593Smuzhiyun 	on |= spec->master_mute;
4586*4882a593Smuzhiyun 	spec->speaker_muted = on;
4587*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4588*4882a593Smuzhiyun 		paths = spec->out_paths;
4589*4882a593Smuzhiyun 	else
4590*4882a593Smuzhiyun 		paths = spec->speaker_paths;
4591*4882a593Smuzhiyun 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
4592*4882a593Smuzhiyun 		    spec->autocfg.speaker_pins, paths, on);
4593*4882a593Smuzhiyun 
4594*4882a593Smuzhiyun 	/* toggle line-out mutes if needed, too */
4595*4882a593Smuzhiyun 	/* if LO is a copy of either HP or Speaker, don't need to handle it */
4596*4882a593Smuzhiyun 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
4597*4882a593Smuzhiyun 	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
4598*4882a593Smuzhiyun 		return;
4599*4882a593Smuzhiyun 	if (!spec->automute_lo)
4600*4882a593Smuzhiyun 		on = 0;
4601*4882a593Smuzhiyun 	else
4602*4882a593Smuzhiyun 		on = spec->hp_jack_present;
4603*4882a593Smuzhiyun 	on |= spec->master_mute;
4604*4882a593Smuzhiyun 	spec->line_out_muted = on;
4605*4882a593Smuzhiyun 	paths = spec->out_paths;
4606*4882a593Smuzhiyun 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4607*4882a593Smuzhiyun 		    spec->autocfg.line_out_pins, paths, on);
4608*4882a593Smuzhiyun }
4609*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_update_outputs);
4610*4882a593Smuzhiyun 
call_update_outputs(struct hda_codec * codec)4611*4882a593Smuzhiyun static void call_update_outputs(struct hda_codec *codec)
4612*4882a593Smuzhiyun {
4613*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4614*4882a593Smuzhiyun 	if (spec->automute_hook)
4615*4882a593Smuzhiyun 		spec->automute_hook(codec);
4616*4882a593Smuzhiyun 	else
4617*4882a593Smuzhiyun 		snd_hda_gen_update_outputs(codec);
4618*4882a593Smuzhiyun 
4619*4882a593Smuzhiyun 	/* sync the whole vmaster followers to reflect the new auto-mute status */
4620*4882a593Smuzhiyun 	if (spec->auto_mute_via_amp && !codec->bus->shutdown)
4621*4882a593Smuzhiyun 		snd_ctl_sync_vmaster(spec->vmaster_mute.sw_kctl, false);
4622*4882a593Smuzhiyun }
4623*4882a593Smuzhiyun 
4624*4882a593Smuzhiyun /**
4625*4882a593Smuzhiyun  * snd_hda_gen_hp_automute - standard HP-automute helper
4626*4882a593Smuzhiyun  * @codec: the HDA codec
4627*4882a593Smuzhiyun  * @jack: jack object, NULL for the whole
4628*4882a593Smuzhiyun  */
snd_hda_gen_hp_automute(struct hda_codec * codec,struct hda_jack_callback * jack)4629*4882a593Smuzhiyun void snd_hda_gen_hp_automute(struct hda_codec *codec,
4630*4882a593Smuzhiyun 			     struct hda_jack_callback *jack)
4631*4882a593Smuzhiyun {
4632*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4633*4882a593Smuzhiyun 	hda_nid_t *pins = spec->autocfg.hp_pins;
4634*4882a593Smuzhiyun 	int num_pins = ARRAY_SIZE(spec->autocfg.hp_pins);
4635*4882a593Smuzhiyun 
4636*4882a593Smuzhiyun 	/* No detection for the first HP jack during indep-HP mode */
4637*4882a593Smuzhiyun 	if (spec->indep_hp_enabled) {
4638*4882a593Smuzhiyun 		pins++;
4639*4882a593Smuzhiyun 		num_pins--;
4640*4882a593Smuzhiyun 	}
4641*4882a593Smuzhiyun 
4642*4882a593Smuzhiyun 	spec->hp_jack_present = detect_jacks(codec, num_pins, pins);
4643*4882a593Smuzhiyun 	if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
4644*4882a593Smuzhiyun 		return;
4645*4882a593Smuzhiyun 	call_update_outputs(codec);
4646*4882a593Smuzhiyun }
4647*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_hp_automute);
4648*4882a593Smuzhiyun 
4649*4882a593Smuzhiyun /**
4650*4882a593Smuzhiyun  * snd_hda_gen_line_automute - standard line-out-automute helper
4651*4882a593Smuzhiyun  * @codec: the HDA codec
4652*4882a593Smuzhiyun  * @jack: jack object, NULL for the whole
4653*4882a593Smuzhiyun  */
snd_hda_gen_line_automute(struct hda_codec * codec,struct hda_jack_callback * jack)4654*4882a593Smuzhiyun void snd_hda_gen_line_automute(struct hda_codec *codec,
4655*4882a593Smuzhiyun 			       struct hda_jack_callback *jack)
4656*4882a593Smuzhiyun {
4657*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4658*4882a593Smuzhiyun 
4659*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
4660*4882a593Smuzhiyun 		return;
4661*4882a593Smuzhiyun 	/* check LO jack only when it's different from HP */
4662*4882a593Smuzhiyun 	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
4663*4882a593Smuzhiyun 		return;
4664*4882a593Smuzhiyun 
4665*4882a593Smuzhiyun 	spec->line_jack_present =
4666*4882a593Smuzhiyun 		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
4667*4882a593Smuzhiyun 			     spec->autocfg.line_out_pins);
4668*4882a593Smuzhiyun 	if (!spec->automute_speaker || !spec->detect_lo)
4669*4882a593Smuzhiyun 		return;
4670*4882a593Smuzhiyun 	call_update_outputs(codec);
4671*4882a593Smuzhiyun }
4672*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_line_automute);
4673*4882a593Smuzhiyun 
4674*4882a593Smuzhiyun /**
4675*4882a593Smuzhiyun  * snd_hda_gen_mic_autoswitch - standard mic auto-switch helper
4676*4882a593Smuzhiyun  * @codec: the HDA codec
4677*4882a593Smuzhiyun  * @jack: jack object, NULL for the whole
4678*4882a593Smuzhiyun  */
snd_hda_gen_mic_autoswitch(struct hda_codec * codec,struct hda_jack_callback * jack)4679*4882a593Smuzhiyun void snd_hda_gen_mic_autoswitch(struct hda_codec *codec,
4680*4882a593Smuzhiyun 				struct hda_jack_callback *jack)
4681*4882a593Smuzhiyun {
4682*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4683*4882a593Smuzhiyun 	int i;
4684*4882a593Smuzhiyun 
4685*4882a593Smuzhiyun 	if (!spec->auto_mic)
4686*4882a593Smuzhiyun 		return;
4687*4882a593Smuzhiyun 
4688*4882a593Smuzhiyun 	for (i = spec->am_num_entries - 1; i > 0; i--) {
4689*4882a593Smuzhiyun 		hda_nid_t pin = spec->am_entry[i].pin;
4690*4882a593Smuzhiyun 		/* don't detect pins retasked as outputs */
4691*4882a593Smuzhiyun 		if (snd_hda_codec_get_pin_target(codec, pin) & AC_PINCTL_OUT_EN)
4692*4882a593Smuzhiyun 			continue;
4693*4882a593Smuzhiyun 		if (snd_hda_jack_detect_state(codec, pin) == HDA_JACK_PRESENT) {
4694*4882a593Smuzhiyun 			mux_select(codec, 0, spec->am_entry[i].idx);
4695*4882a593Smuzhiyun 			return;
4696*4882a593Smuzhiyun 		}
4697*4882a593Smuzhiyun 	}
4698*4882a593Smuzhiyun 	mux_select(codec, 0, spec->am_entry[0].idx);
4699*4882a593Smuzhiyun }
4700*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_mic_autoswitch);
4701*4882a593Smuzhiyun 
4702*4882a593Smuzhiyun /* call appropriate hooks */
call_hp_automute(struct hda_codec * codec,struct hda_jack_callback * jack)4703*4882a593Smuzhiyun static void call_hp_automute(struct hda_codec *codec,
4704*4882a593Smuzhiyun 			     struct hda_jack_callback *jack)
4705*4882a593Smuzhiyun {
4706*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4707*4882a593Smuzhiyun 	if (spec->hp_automute_hook)
4708*4882a593Smuzhiyun 		spec->hp_automute_hook(codec, jack);
4709*4882a593Smuzhiyun 	else
4710*4882a593Smuzhiyun 		snd_hda_gen_hp_automute(codec, jack);
4711*4882a593Smuzhiyun }
4712*4882a593Smuzhiyun 
call_line_automute(struct hda_codec * codec,struct hda_jack_callback * jack)4713*4882a593Smuzhiyun static void call_line_automute(struct hda_codec *codec,
4714*4882a593Smuzhiyun 			       struct hda_jack_callback *jack)
4715*4882a593Smuzhiyun {
4716*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4717*4882a593Smuzhiyun 	if (spec->line_automute_hook)
4718*4882a593Smuzhiyun 		spec->line_automute_hook(codec, jack);
4719*4882a593Smuzhiyun 	else
4720*4882a593Smuzhiyun 		snd_hda_gen_line_automute(codec, jack);
4721*4882a593Smuzhiyun }
4722*4882a593Smuzhiyun 
call_mic_autoswitch(struct hda_codec * codec,struct hda_jack_callback * jack)4723*4882a593Smuzhiyun static void call_mic_autoswitch(struct hda_codec *codec,
4724*4882a593Smuzhiyun 				struct hda_jack_callback *jack)
4725*4882a593Smuzhiyun {
4726*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4727*4882a593Smuzhiyun 	if (spec->mic_autoswitch_hook)
4728*4882a593Smuzhiyun 		spec->mic_autoswitch_hook(codec, jack);
4729*4882a593Smuzhiyun 	else
4730*4882a593Smuzhiyun 		snd_hda_gen_mic_autoswitch(codec, jack);
4731*4882a593Smuzhiyun }
4732*4882a593Smuzhiyun 
4733*4882a593Smuzhiyun /* update jack retasking */
update_automute_all(struct hda_codec * codec)4734*4882a593Smuzhiyun static void update_automute_all(struct hda_codec *codec)
4735*4882a593Smuzhiyun {
4736*4882a593Smuzhiyun 	call_hp_automute(codec, NULL);
4737*4882a593Smuzhiyun 	call_line_automute(codec, NULL);
4738*4882a593Smuzhiyun 	call_mic_autoswitch(codec, NULL);
4739*4882a593Smuzhiyun }
4740*4882a593Smuzhiyun 
4741*4882a593Smuzhiyun /*
4742*4882a593Smuzhiyun  * Auto-Mute mode mixer enum support
4743*4882a593Smuzhiyun  */
automute_mode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)4744*4882a593Smuzhiyun static int automute_mode_info(struct snd_kcontrol *kcontrol,
4745*4882a593Smuzhiyun 			      struct snd_ctl_elem_info *uinfo)
4746*4882a593Smuzhiyun {
4747*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4748*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4749*4882a593Smuzhiyun 	static const char * const texts3[] = {
4750*4882a593Smuzhiyun 		"Disabled", "Speaker Only", "Line Out+Speaker"
4751*4882a593Smuzhiyun 	};
4752*4882a593Smuzhiyun 
4753*4882a593Smuzhiyun 	if (spec->automute_speaker_possible && spec->automute_lo_possible)
4754*4882a593Smuzhiyun 		return snd_hda_enum_helper_info(kcontrol, uinfo, 3, texts3);
4755*4882a593Smuzhiyun 	return snd_hda_enum_bool_helper_info(kcontrol, uinfo);
4756*4882a593Smuzhiyun }
4757*4882a593Smuzhiyun 
automute_mode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4758*4882a593Smuzhiyun static int automute_mode_get(struct snd_kcontrol *kcontrol,
4759*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
4760*4882a593Smuzhiyun {
4761*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4762*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4763*4882a593Smuzhiyun 	unsigned int val = 0;
4764*4882a593Smuzhiyun 	if (spec->automute_speaker)
4765*4882a593Smuzhiyun 		val++;
4766*4882a593Smuzhiyun 	if (spec->automute_lo)
4767*4882a593Smuzhiyun 		val++;
4768*4882a593Smuzhiyun 
4769*4882a593Smuzhiyun 	ucontrol->value.enumerated.item[0] = val;
4770*4882a593Smuzhiyun 	return 0;
4771*4882a593Smuzhiyun }
4772*4882a593Smuzhiyun 
automute_mode_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)4773*4882a593Smuzhiyun static int automute_mode_put(struct snd_kcontrol *kcontrol,
4774*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
4775*4882a593Smuzhiyun {
4776*4882a593Smuzhiyun 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
4777*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4778*4882a593Smuzhiyun 
4779*4882a593Smuzhiyun 	switch (ucontrol->value.enumerated.item[0]) {
4780*4882a593Smuzhiyun 	case 0:
4781*4882a593Smuzhiyun 		if (!spec->automute_speaker && !spec->automute_lo)
4782*4882a593Smuzhiyun 			return 0;
4783*4882a593Smuzhiyun 		spec->automute_speaker = 0;
4784*4882a593Smuzhiyun 		spec->automute_lo = 0;
4785*4882a593Smuzhiyun 		break;
4786*4882a593Smuzhiyun 	case 1:
4787*4882a593Smuzhiyun 		if (spec->automute_speaker_possible) {
4788*4882a593Smuzhiyun 			if (!spec->automute_lo && spec->automute_speaker)
4789*4882a593Smuzhiyun 				return 0;
4790*4882a593Smuzhiyun 			spec->automute_speaker = 1;
4791*4882a593Smuzhiyun 			spec->automute_lo = 0;
4792*4882a593Smuzhiyun 		} else if (spec->automute_lo_possible) {
4793*4882a593Smuzhiyun 			if (spec->automute_lo)
4794*4882a593Smuzhiyun 				return 0;
4795*4882a593Smuzhiyun 			spec->automute_lo = 1;
4796*4882a593Smuzhiyun 		} else
4797*4882a593Smuzhiyun 			return -EINVAL;
4798*4882a593Smuzhiyun 		break;
4799*4882a593Smuzhiyun 	case 2:
4800*4882a593Smuzhiyun 		if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
4801*4882a593Smuzhiyun 			return -EINVAL;
4802*4882a593Smuzhiyun 		if (spec->automute_speaker && spec->automute_lo)
4803*4882a593Smuzhiyun 			return 0;
4804*4882a593Smuzhiyun 		spec->automute_speaker = 1;
4805*4882a593Smuzhiyun 		spec->automute_lo = 1;
4806*4882a593Smuzhiyun 		break;
4807*4882a593Smuzhiyun 	default:
4808*4882a593Smuzhiyun 		return -EINVAL;
4809*4882a593Smuzhiyun 	}
4810*4882a593Smuzhiyun 	call_update_outputs(codec);
4811*4882a593Smuzhiyun 	return 1;
4812*4882a593Smuzhiyun }
4813*4882a593Smuzhiyun 
4814*4882a593Smuzhiyun static const struct snd_kcontrol_new automute_mode_enum = {
4815*4882a593Smuzhiyun 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4816*4882a593Smuzhiyun 	.name = "Auto-Mute Mode",
4817*4882a593Smuzhiyun 	.info = automute_mode_info,
4818*4882a593Smuzhiyun 	.get = automute_mode_get,
4819*4882a593Smuzhiyun 	.put = automute_mode_put,
4820*4882a593Smuzhiyun };
4821*4882a593Smuzhiyun 
add_automute_mode_enum(struct hda_codec * codec)4822*4882a593Smuzhiyun static int add_automute_mode_enum(struct hda_codec *codec)
4823*4882a593Smuzhiyun {
4824*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4825*4882a593Smuzhiyun 
4826*4882a593Smuzhiyun 	if (!snd_hda_gen_add_kctl(spec, NULL, &automute_mode_enum))
4827*4882a593Smuzhiyun 		return -ENOMEM;
4828*4882a593Smuzhiyun 	return 0;
4829*4882a593Smuzhiyun }
4830*4882a593Smuzhiyun 
4831*4882a593Smuzhiyun /*
4832*4882a593Smuzhiyun  * Check the availability of HP/line-out auto-mute;
4833*4882a593Smuzhiyun  * Set up appropriately if really supported
4834*4882a593Smuzhiyun  */
check_auto_mute_availability(struct hda_codec * codec)4835*4882a593Smuzhiyun static int check_auto_mute_availability(struct hda_codec *codec)
4836*4882a593Smuzhiyun {
4837*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4838*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
4839*4882a593Smuzhiyun 	int present = 0;
4840*4882a593Smuzhiyun 	int i, err;
4841*4882a593Smuzhiyun 
4842*4882a593Smuzhiyun 	if (spec->suppress_auto_mute)
4843*4882a593Smuzhiyun 		return 0;
4844*4882a593Smuzhiyun 
4845*4882a593Smuzhiyun 	if (cfg->hp_pins[0])
4846*4882a593Smuzhiyun 		present++;
4847*4882a593Smuzhiyun 	if (cfg->line_out_pins[0])
4848*4882a593Smuzhiyun 		present++;
4849*4882a593Smuzhiyun 	if (cfg->speaker_pins[0])
4850*4882a593Smuzhiyun 		present++;
4851*4882a593Smuzhiyun 	if (present < 2) /* need two different output types */
4852*4882a593Smuzhiyun 		return 0;
4853*4882a593Smuzhiyun 
4854*4882a593Smuzhiyun 	if (!cfg->speaker_pins[0] &&
4855*4882a593Smuzhiyun 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
4856*4882a593Smuzhiyun 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
4857*4882a593Smuzhiyun 		       sizeof(cfg->speaker_pins));
4858*4882a593Smuzhiyun 		cfg->speaker_outs = cfg->line_outs;
4859*4882a593Smuzhiyun 	}
4860*4882a593Smuzhiyun 
4861*4882a593Smuzhiyun 	if (!cfg->hp_pins[0] &&
4862*4882a593Smuzhiyun 	    cfg->line_out_type == AUTO_PIN_HP_OUT) {
4863*4882a593Smuzhiyun 		memcpy(cfg->hp_pins, cfg->line_out_pins,
4864*4882a593Smuzhiyun 		       sizeof(cfg->hp_pins));
4865*4882a593Smuzhiyun 		cfg->hp_outs = cfg->line_outs;
4866*4882a593Smuzhiyun 	}
4867*4882a593Smuzhiyun 
4868*4882a593Smuzhiyun 	for (i = 0; i < cfg->hp_outs; i++) {
4869*4882a593Smuzhiyun 		hda_nid_t nid = cfg->hp_pins[i];
4870*4882a593Smuzhiyun 		if (!is_jack_detectable(codec, nid))
4871*4882a593Smuzhiyun 			continue;
4872*4882a593Smuzhiyun 		codec_dbg(codec, "Enable HP auto-muting on NID 0x%x\n", nid);
4873*4882a593Smuzhiyun 		snd_hda_jack_detect_enable_callback(codec, nid,
4874*4882a593Smuzhiyun 						    call_hp_automute);
4875*4882a593Smuzhiyun 		spec->detect_hp = 1;
4876*4882a593Smuzhiyun 	}
4877*4882a593Smuzhiyun 
4878*4882a593Smuzhiyun 	if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
4879*4882a593Smuzhiyun 		if (cfg->speaker_outs)
4880*4882a593Smuzhiyun 			for (i = 0; i < cfg->line_outs; i++) {
4881*4882a593Smuzhiyun 				hda_nid_t nid = cfg->line_out_pins[i];
4882*4882a593Smuzhiyun 				if (!is_jack_detectable(codec, nid))
4883*4882a593Smuzhiyun 					continue;
4884*4882a593Smuzhiyun 				codec_dbg(codec, "Enable Line-Out auto-muting on NID 0x%x\n", nid);
4885*4882a593Smuzhiyun 				snd_hda_jack_detect_enable_callback(codec, nid,
4886*4882a593Smuzhiyun 								    call_line_automute);
4887*4882a593Smuzhiyun 				spec->detect_lo = 1;
4888*4882a593Smuzhiyun 			}
4889*4882a593Smuzhiyun 		spec->automute_lo_possible = spec->detect_hp;
4890*4882a593Smuzhiyun 	}
4891*4882a593Smuzhiyun 
4892*4882a593Smuzhiyun 	spec->automute_speaker_possible = cfg->speaker_outs &&
4893*4882a593Smuzhiyun 		(spec->detect_hp || spec->detect_lo);
4894*4882a593Smuzhiyun 
4895*4882a593Smuzhiyun 	spec->automute_lo = spec->automute_lo_possible;
4896*4882a593Smuzhiyun 	spec->automute_speaker = spec->automute_speaker_possible;
4897*4882a593Smuzhiyun 
4898*4882a593Smuzhiyun 	if (spec->automute_speaker_possible || spec->automute_lo_possible) {
4899*4882a593Smuzhiyun 		/* create a control for automute mode */
4900*4882a593Smuzhiyun 		err = add_automute_mode_enum(codec);
4901*4882a593Smuzhiyun 		if (err < 0)
4902*4882a593Smuzhiyun 			return err;
4903*4882a593Smuzhiyun 	}
4904*4882a593Smuzhiyun 	return 0;
4905*4882a593Smuzhiyun }
4906*4882a593Smuzhiyun 
4907*4882a593Smuzhiyun /* check whether all auto-mic pins are valid; setup indices if OK */
auto_mic_check_imux(struct hda_codec * codec)4908*4882a593Smuzhiyun static bool auto_mic_check_imux(struct hda_codec *codec)
4909*4882a593Smuzhiyun {
4910*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4911*4882a593Smuzhiyun 	const struct hda_input_mux *imux;
4912*4882a593Smuzhiyun 	int i;
4913*4882a593Smuzhiyun 
4914*4882a593Smuzhiyun 	imux = &spec->input_mux;
4915*4882a593Smuzhiyun 	for (i = 0; i < spec->am_num_entries; i++) {
4916*4882a593Smuzhiyun 		spec->am_entry[i].idx =
4917*4882a593Smuzhiyun 			find_idx_in_nid_list(spec->am_entry[i].pin,
4918*4882a593Smuzhiyun 					     spec->imux_pins, imux->num_items);
4919*4882a593Smuzhiyun 		if (spec->am_entry[i].idx < 0)
4920*4882a593Smuzhiyun 			return false; /* no corresponding imux */
4921*4882a593Smuzhiyun 	}
4922*4882a593Smuzhiyun 
4923*4882a593Smuzhiyun 	/* we don't need the jack detection for the first pin */
4924*4882a593Smuzhiyun 	for (i = 1; i < spec->am_num_entries; i++)
4925*4882a593Smuzhiyun 		snd_hda_jack_detect_enable_callback(codec,
4926*4882a593Smuzhiyun 						    spec->am_entry[i].pin,
4927*4882a593Smuzhiyun 						    call_mic_autoswitch);
4928*4882a593Smuzhiyun 	return true;
4929*4882a593Smuzhiyun }
4930*4882a593Smuzhiyun 
compare_attr(const void * ap,const void * bp)4931*4882a593Smuzhiyun static int compare_attr(const void *ap, const void *bp)
4932*4882a593Smuzhiyun {
4933*4882a593Smuzhiyun 	const struct automic_entry *a = ap;
4934*4882a593Smuzhiyun 	const struct automic_entry *b = bp;
4935*4882a593Smuzhiyun 	return (int)(a->attr - b->attr);
4936*4882a593Smuzhiyun }
4937*4882a593Smuzhiyun 
4938*4882a593Smuzhiyun /*
4939*4882a593Smuzhiyun  * Check the availability of auto-mic switch;
4940*4882a593Smuzhiyun  * Set up if really supported
4941*4882a593Smuzhiyun  */
check_auto_mic_availability(struct hda_codec * codec)4942*4882a593Smuzhiyun static int check_auto_mic_availability(struct hda_codec *codec)
4943*4882a593Smuzhiyun {
4944*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
4945*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
4946*4882a593Smuzhiyun 	unsigned int types;
4947*4882a593Smuzhiyun 	int i, num_pins;
4948*4882a593Smuzhiyun 
4949*4882a593Smuzhiyun 	if (spec->suppress_auto_mic)
4950*4882a593Smuzhiyun 		return 0;
4951*4882a593Smuzhiyun 
4952*4882a593Smuzhiyun 	types = 0;
4953*4882a593Smuzhiyun 	num_pins = 0;
4954*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++) {
4955*4882a593Smuzhiyun 		hda_nid_t nid = cfg->inputs[i].pin;
4956*4882a593Smuzhiyun 		unsigned int attr;
4957*4882a593Smuzhiyun 		attr = snd_hda_codec_get_pincfg(codec, nid);
4958*4882a593Smuzhiyun 		attr = snd_hda_get_input_pin_attr(attr);
4959*4882a593Smuzhiyun 		if (types & (1 << attr))
4960*4882a593Smuzhiyun 			return 0; /* already occupied */
4961*4882a593Smuzhiyun 		switch (attr) {
4962*4882a593Smuzhiyun 		case INPUT_PIN_ATTR_INT:
4963*4882a593Smuzhiyun 			if (cfg->inputs[i].type != AUTO_PIN_MIC)
4964*4882a593Smuzhiyun 				return 0; /* invalid type */
4965*4882a593Smuzhiyun 			break;
4966*4882a593Smuzhiyun 		case INPUT_PIN_ATTR_UNUSED:
4967*4882a593Smuzhiyun 			return 0; /* invalid entry */
4968*4882a593Smuzhiyun 		default:
4969*4882a593Smuzhiyun 			if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
4970*4882a593Smuzhiyun 				return 0; /* invalid type */
4971*4882a593Smuzhiyun 			if (!spec->line_in_auto_switch &&
4972*4882a593Smuzhiyun 			    cfg->inputs[i].type != AUTO_PIN_MIC)
4973*4882a593Smuzhiyun 				return 0; /* only mic is allowed */
4974*4882a593Smuzhiyun 			if (!is_jack_detectable(codec, nid))
4975*4882a593Smuzhiyun 				return 0; /* no unsol support */
4976*4882a593Smuzhiyun 			break;
4977*4882a593Smuzhiyun 		}
4978*4882a593Smuzhiyun 		if (num_pins >= MAX_AUTO_MIC_PINS)
4979*4882a593Smuzhiyun 			return 0;
4980*4882a593Smuzhiyun 		types |= (1 << attr);
4981*4882a593Smuzhiyun 		spec->am_entry[num_pins].pin = nid;
4982*4882a593Smuzhiyun 		spec->am_entry[num_pins].attr = attr;
4983*4882a593Smuzhiyun 		num_pins++;
4984*4882a593Smuzhiyun 	}
4985*4882a593Smuzhiyun 
4986*4882a593Smuzhiyun 	if (num_pins < 2)
4987*4882a593Smuzhiyun 		return 0;
4988*4882a593Smuzhiyun 
4989*4882a593Smuzhiyun 	spec->am_num_entries = num_pins;
4990*4882a593Smuzhiyun 	/* sort the am_entry in the order of attr so that the pin with a
4991*4882a593Smuzhiyun 	 * higher attr will be selected when the jack is plugged.
4992*4882a593Smuzhiyun 	 */
4993*4882a593Smuzhiyun 	sort(spec->am_entry, num_pins, sizeof(spec->am_entry[0]),
4994*4882a593Smuzhiyun 	     compare_attr, NULL);
4995*4882a593Smuzhiyun 
4996*4882a593Smuzhiyun 	if (!auto_mic_check_imux(codec))
4997*4882a593Smuzhiyun 		return 0;
4998*4882a593Smuzhiyun 
4999*4882a593Smuzhiyun 	spec->auto_mic = 1;
5000*4882a593Smuzhiyun 	spec->num_adc_nids = 1;
5001*4882a593Smuzhiyun 	spec->cur_mux[0] = spec->am_entry[0].idx;
5002*4882a593Smuzhiyun 	codec_dbg(codec, "Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
5003*4882a593Smuzhiyun 		    spec->am_entry[0].pin,
5004*4882a593Smuzhiyun 		    spec->am_entry[1].pin,
5005*4882a593Smuzhiyun 		    spec->am_entry[2].pin);
5006*4882a593Smuzhiyun 
5007*4882a593Smuzhiyun 	return 0;
5008*4882a593Smuzhiyun }
5009*4882a593Smuzhiyun 
5010*4882a593Smuzhiyun /**
5011*4882a593Smuzhiyun  * snd_hda_gen_path_power_filter - power_filter hook to make inactive widgets
5012*4882a593Smuzhiyun  * into power down
5013*4882a593Smuzhiyun  * @codec: the HDA codec
5014*4882a593Smuzhiyun  * @nid: NID to evalute
5015*4882a593Smuzhiyun  * @power_state: target power state
5016*4882a593Smuzhiyun  */
snd_hda_gen_path_power_filter(struct hda_codec * codec,hda_nid_t nid,unsigned int power_state)5017*4882a593Smuzhiyun unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
5018*4882a593Smuzhiyun 						  hda_nid_t nid,
5019*4882a593Smuzhiyun 						  unsigned int power_state)
5020*4882a593Smuzhiyun {
5021*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5022*4882a593Smuzhiyun 
5023*4882a593Smuzhiyun 	if (!spec->power_down_unused && !codec->power_save_node)
5024*4882a593Smuzhiyun 		return power_state;
5025*4882a593Smuzhiyun 	if (power_state != AC_PWRST_D0 || nid == codec->core.afg)
5026*4882a593Smuzhiyun 		return power_state;
5027*4882a593Smuzhiyun 	if (get_wcaps_type(get_wcaps(codec, nid)) >= AC_WID_POWER)
5028*4882a593Smuzhiyun 		return power_state;
5029*4882a593Smuzhiyun 	if (is_active_nid_for_any(codec, nid))
5030*4882a593Smuzhiyun 		return power_state;
5031*4882a593Smuzhiyun 	return AC_PWRST_D3;
5032*4882a593Smuzhiyun }
5033*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_path_power_filter);
5034*4882a593Smuzhiyun 
5035*4882a593Smuzhiyun /* mute all aamix inputs initially; parse up to the first leaves */
mute_all_mixer_nid(struct hda_codec * codec,hda_nid_t mix)5036*4882a593Smuzhiyun static void mute_all_mixer_nid(struct hda_codec *codec, hda_nid_t mix)
5037*4882a593Smuzhiyun {
5038*4882a593Smuzhiyun 	int i, nums;
5039*4882a593Smuzhiyun 	const hda_nid_t *conn;
5040*4882a593Smuzhiyun 	bool has_amp;
5041*4882a593Smuzhiyun 
5042*4882a593Smuzhiyun 	nums = snd_hda_get_conn_list(codec, mix, &conn);
5043*4882a593Smuzhiyun 	has_amp = nid_has_mute(codec, mix, HDA_INPUT);
5044*4882a593Smuzhiyun 	for (i = 0; i < nums; i++) {
5045*4882a593Smuzhiyun 		if (has_amp)
5046*4882a593Smuzhiyun 			update_amp(codec, mix, HDA_INPUT, i,
5047*4882a593Smuzhiyun 				   0xff, HDA_AMP_MUTE);
5048*4882a593Smuzhiyun 		else if (nid_has_volume(codec, conn[i], HDA_OUTPUT))
5049*4882a593Smuzhiyun 			update_amp(codec, conn[i], HDA_OUTPUT, 0,
5050*4882a593Smuzhiyun 				   0xff, HDA_AMP_MUTE);
5051*4882a593Smuzhiyun 	}
5052*4882a593Smuzhiyun }
5053*4882a593Smuzhiyun 
5054*4882a593Smuzhiyun /**
5055*4882a593Smuzhiyun  * snd_hda_gen_stream_pm - Stream power management callback
5056*4882a593Smuzhiyun  * @codec: the HDA codec
5057*4882a593Smuzhiyun  * @nid: audio widget
5058*4882a593Smuzhiyun  * @on: power on/off flag
5059*4882a593Smuzhiyun  *
5060*4882a593Smuzhiyun  * Set this in patch_ops.stream_pm.  Only valid with power_save_node flag.
5061*4882a593Smuzhiyun  */
snd_hda_gen_stream_pm(struct hda_codec * codec,hda_nid_t nid,bool on)5062*4882a593Smuzhiyun void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on)
5063*4882a593Smuzhiyun {
5064*4882a593Smuzhiyun 	if (codec->power_save_node)
5065*4882a593Smuzhiyun 		set_path_power(codec, nid, -1, on);
5066*4882a593Smuzhiyun }
5067*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_stream_pm);
5068*4882a593Smuzhiyun 
5069*4882a593Smuzhiyun /**
5070*4882a593Smuzhiyun  * snd_hda_gen_parse_auto_config - Parse the given BIOS configuration and
5071*4882a593Smuzhiyun  * set up the hda_gen_spec
5072*4882a593Smuzhiyun  * @codec: the HDA codec
5073*4882a593Smuzhiyun  * @cfg: Parsed pin configuration
5074*4882a593Smuzhiyun  *
5075*4882a593Smuzhiyun  * return 1 if successful, 0 if the proper config is not found,
5076*4882a593Smuzhiyun  * or a negative error code
5077*4882a593Smuzhiyun  */
snd_hda_gen_parse_auto_config(struct hda_codec * codec,struct auto_pin_cfg * cfg)5078*4882a593Smuzhiyun int snd_hda_gen_parse_auto_config(struct hda_codec *codec,
5079*4882a593Smuzhiyun 				  struct auto_pin_cfg *cfg)
5080*4882a593Smuzhiyun {
5081*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5082*4882a593Smuzhiyun 	int err;
5083*4882a593Smuzhiyun 
5084*4882a593Smuzhiyun 	parse_user_hints(codec);
5085*4882a593Smuzhiyun 
5086*4882a593Smuzhiyun 	if (spec->mixer_nid && !spec->mixer_merge_nid)
5087*4882a593Smuzhiyun 		spec->mixer_merge_nid = spec->mixer_nid;
5088*4882a593Smuzhiyun 
5089*4882a593Smuzhiyun 	if (cfg != &spec->autocfg) {
5090*4882a593Smuzhiyun 		spec->autocfg = *cfg;
5091*4882a593Smuzhiyun 		cfg = &spec->autocfg;
5092*4882a593Smuzhiyun 	}
5093*4882a593Smuzhiyun 
5094*4882a593Smuzhiyun 	if (!spec->main_out_badness)
5095*4882a593Smuzhiyun 		spec->main_out_badness = &hda_main_out_badness;
5096*4882a593Smuzhiyun 	if (!spec->extra_out_badness)
5097*4882a593Smuzhiyun 		spec->extra_out_badness = &hda_extra_out_badness;
5098*4882a593Smuzhiyun 
5099*4882a593Smuzhiyun 	fill_all_dac_nids(codec);
5100*4882a593Smuzhiyun 
5101*4882a593Smuzhiyun 	if (!cfg->line_outs) {
5102*4882a593Smuzhiyun 		if (cfg->dig_outs || cfg->dig_in_pin) {
5103*4882a593Smuzhiyun 			spec->multiout.max_channels = 2;
5104*4882a593Smuzhiyun 			spec->no_analog = 1;
5105*4882a593Smuzhiyun 			goto dig_only;
5106*4882a593Smuzhiyun 		}
5107*4882a593Smuzhiyun 		if (!cfg->num_inputs && !cfg->dig_in_pin)
5108*4882a593Smuzhiyun 			return 0; /* can't find valid BIOS pin config */
5109*4882a593Smuzhiyun 	}
5110*4882a593Smuzhiyun 
5111*4882a593Smuzhiyun 	if (!spec->no_primary_hp &&
5112*4882a593Smuzhiyun 	    cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
5113*4882a593Smuzhiyun 	    cfg->line_outs <= cfg->hp_outs) {
5114*4882a593Smuzhiyun 		/* use HP as primary out */
5115*4882a593Smuzhiyun 		cfg->speaker_outs = cfg->line_outs;
5116*4882a593Smuzhiyun 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
5117*4882a593Smuzhiyun 		       sizeof(cfg->speaker_pins));
5118*4882a593Smuzhiyun 		cfg->line_outs = cfg->hp_outs;
5119*4882a593Smuzhiyun 		memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
5120*4882a593Smuzhiyun 		cfg->hp_outs = 0;
5121*4882a593Smuzhiyun 		memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
5122*4882a593Smuzhiyun 		cfg->line_out_type = AUTO_PIN_HP_OUT;
5123*4882a593Smuzhiyun 	}
5124*4882a593Smuzhiyun 
5125*4882a593Smuzhiyun 	err = parse_output_paths(codec);
5126*4882a593Smuzhiyun 	if (err < 0)
5127*4882a593Smuzhiyun 		return err;
5128*4882a593Smuzhiyun 	err = create_multi_channel_mode(codec);
5129*4882a593Smuzhiyun 	if (err < 0)
5130*4882a593Smuzhiyun 		return err;
5131*4882a593Smuzhiyun 	err = create_multi_out_ctls(codec, cfg);
5132*4882a593Smuzhiyun 	if (err < 0)
5133*4882a593Smuzhiyun 		return err;
5134*4882a593Smuzhiyun 	err = create_hp_out_ctls(codec);
5135*4882a593Smuzhiyun 	if (err < 0)
5136*4882a593Smuzhiyun 		return err;
5137*4882a593Smuzhiyun 	err = create_speaker_out_ctls(codec);
5138*4882a593Smuzhiyun 	if (err < 0)
5139*4882a593Smuzhiyun 		return err;
5140*4882a593Smuzhiyun 	err = create_indep_hp_ctls(codec);
5141*4882a593Smuzhiyun 	if (err < 0)
5142*4882a593Smuzhiyun 		return err;
5143*4882a593Smuzhiyun 	err = create_loopback_mixing_ctl(codec);
5144*4882a593Smuzhiyun 	if (err < 0)
5145*4882a593Smuzhiyun 		return err;
5146*4882a593Smuzhiyun 	err = create_hp_mic(codec);
5147*4882a593Smuzhiyun 	if (err < 0)
5148*4882a593Smuzhiyun 		return err;
5149*4882a593Smuzhiyun 	err = create_input_ctls(codec);
5150*4882a593Smuzhiyun 	if (err < 0)
5151*4882a593Smuzhiyun 		return err;
5152*4882a593Smuzhiyun 
5153*4882a593Smuzhiyun 	/* add power-down pin callbacks at first */
5154*4882a593Smuzhiyun 	add_all_pin_power_ctls(codec, false);
5155*4882a593Smuzhiyun 
5156*4882a593Smuzhiyun 	spec->const_channel_count = spec->ext_channel_count;
5157*4882a593Smuzhiyun 	/* check the multiple speaker and headphone pins */
5158*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
5159*4882a593Smuzhiyun 		spec->const_channel_count = max(spec->const_channel_count,
5160*4882a593Smuzhiyun 						cfg->speaker_outs * 2);
5161*4882a593Smuzhiyun 	if (cfg->line_out_type != AUTO_PIN_HP_OUT)
5162*4882a593Smuzhiyun 		spec->const_channel_count = max(spec->const_channel_count,
5163*4882a593Smuzhiyun 						cfg->hp_outs * 2);
5164*4882a593Smuzhiyun 	spec->multiout.max_channels = max(spec->ext_channel_count,
5165*4882a593Smuzhiyun 					  spec->const_channel_count);
5166*4882a593Smuzhiyun 
5167*4882a593Smuzhiyun 	err = check_auto_mute_availability(codec);
5168*4882a593Smuzhiyun 	if (err < 0)
5169*4882a593Smuzhiyun 		return err;
5170*4882a593Smuzhiyun 
5171*4882a593Smuzhiyun 	err = check_dyn_adc_switch(codec);
5172*4882a593Smuzhiyun 	if (err < 0)
5173*4882a593Smuzhiyun 		return err;
5174*4882a593Smuzhiyun 
5175*4882a593Smuzhiyun 	err = check_auto_mic_availability(codec);
5176*4882a593Smuzhiyun 	if (err < 0)
5177*4882a593Smuzhiyun 		return err;
5178*4882a593Smuzhiyun 
5179*4882a593Smuzhiyun 	/* add stereo mix if available and not enabled yet */
5180*4882a593Smuzhiyun 	if (!spec->auto_mic && spec->mixer_nid &&
5181*4882a593Smuzhiyun 	    spec->add_stereo_mix_input == HDA_HINT_STEREO_MIX_AUTO &&
5182*4882a593Smuzhiyun 	    spec->input_mux.num_items > 1) {
5183*4882a593Smuzhiyun 		err = parse_capture_source(codec, spec->mixer_nid,
5184*4882a593Smuzhiyun 					   CFG_IDX_MIX, spec->num_all_adcs,
5185*4882a593Smuzhiyun 					   "Stereo Mix", 0);
5186*4882a593Smuzhiyun 		if (err < 0)
5187*4882a593Smuzhiyun 			return err;
5188*4882a593Smuzhiyun 	}
5189*4882a593Smuzhiyun 
5190*4882a593Smuzhiyun 
5191*4882a593Smuzhiyun 	err = create_capture_mixers(codec);
5192*4882a593Smuzhiyun 	if (err < 0)
5193*4882a593Smuzhiyun 		return err;
5194*4882a593Smuzhiyun 
5195*4882a593Smuzhiyun 	err = parse_mic_boost(codec);
5196*4882a593Smuzhiyun 	if (err < 0)
5197*4882a593Smuzhiyun 		return err;
5198*4882a593Smuzhiyun 
5199*4882a593Smuzhiyun 	/* create "Headphone Mic Jack Mode" if no input selection is
5200*4882a593Smuzhiyun 	 * available (or user specifies add_jack_modes hint)
5201*4882a593Smuzhiyun 	 */
5202*4882a593Smuzhiyun 	if (spec->hp_mic_pin &&
5203*4882a593Smuzhiyun 	    (spec->auto_mic || spec->input_mux.num_items == 1 ||
5204*4882a593Smuzhiyun 	     spec->add_jack_modes)) {
5205*4882a593Smuzhiyun 		err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin);
5206*4882a593Smuzhiyun 		if (err < 0)
5207*4882a593Smuzhiyun 			return err;
5208*4882a593Smuzhiyun 	}
5209*4882a593Smuzhiyun 
5210*4882a593Smuzhiyun 	if (spec->add_jack_modes) {
5211*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
5212*4882a593Smuzhiyun 			err = create_out_jack_modes(codec, cfg->line_outs,
5213*4882a593Smuzhiyun 						    cfg->line_out_pins);
5214*4882a593Smuzhiyun 			if (err < 0)
5215*4882a593Smuzhiyun 				return err;
5216*4882a593Smuzhiyun 		}
5217*4882a593Smuzhiyun 		if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
5218*4882a593Smuzhiyun 			err = create_out_jack_modes(codec, cfg->hp_outs,
5219*4882a593Smuzhiyun 						    cfg->hp_pins);
5220*4882a593Smuzhiyun 			if (err < 0)
5221*4882a593Smuzhiyun 				return err;
5222*4882a593Smuzhiyun 		}
5223*4882a593Smuzhiyun 	}
5224*4882a593Smuzhiyun 
5225*4882a593Smuzhiyun 	/* add power-up pin callbacks at last */
5226*4882a593Smuzhiyun 	add_all_pin_power_ctls(codec, true);
5227*4882a593Smuzhiyun 
5228*4882a593Smuzhiyun 	/* mute all aamix input initially */
5229*4882a593Smuzhiyun 	if (spec->mixer_nid)
5230*4882a593Smuzhiyun 		mute_all_mixer_nid(codec, spec->mixer_nid);
5231*4882a593Smuzhiyun 
5232*4882a593Smuzhiyun  dig_only:
5233*4882a593Smuzhiyun 	parse_digital(codec);
5234*4882a593Smuzhiyun 
5235*4882a593Smuzhiyun 	if (spec->power_down_unused || codec->power_save_node) {
5236*4882a593Smuzhiyun 		if (!codec->power_filter)
5237*4882a593Smuzhiyun 			codec->power_filter = snd_hda_gen_path_power_filter;
5238*4882a593Smuzhiyun 		if (!codec->patch_ops.stream_pm)
5239*4882a593Smuzhiyun 			codec->patch_ops.stream_pm = snd_hda_gen_stream_pm;
5240*4882a593Smuzhiyun 	}
5241*4882a593Smuzhiyun 
5242*4882a593Smuzhiyun 	if (!spec->no_analog && spec->beep_nid) {
5243*4882a593Smuzhiyun 		err = snd_hda_attach_beep_device(codec, spec->beep_nid);
5244*4882a593Smuzhiyun 		if (err < 0)
5245*4882a593Smuzhiyun 			return err;
5246*4882a593Smuzhiyun 		if (codec->beep && codec->power_save_node) {
5247*4882a593Smuzhiyun 			err = add_fake_beep_paths(codec);
5248*4882a593Smuzhiyun 			if (err < 0)
5249*4882a593Smuzhiyun 				return err;
5250*4882a593Smuzhiyun 			codec->beep->power_hook = beep_power_hook;
5251*4882a593Smuzhiyun 		}
5252*4882a593Smuzhiyun 	}
5253*4882a593Smuzhiyun 
5254*4882a593Smuzhiyun 	return 1;
5255*4882a593Smuzhiyun }
5256*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_parse_auto_config);
5257*4882a593Smuzhiyun 
5258*4882a593Smuzhiyun 
5259*4882a593Smuzhiyun /*
5260*4882a593Smuzhiyun  * Build control elements
5261*4882a593Smuzhiyun  */
5262*4882a593Smuzhiyun 
5263*4882a593Smuzhiyun /* follower controls for virtual master */
5264*4882a593Smuzhiyun static const char * const follower_pfxs[] = {
5265*4882a593Smuzhiyun 	"Front", "Surround", "Center", "LFE", "Side",
5266*4882a593Smuzhiyun 	"Headphone", "Speaker", "Mono", "Line Out",
5267*4882a593Smuzhiyun 	"CLFE", "Bass Speaker", "PCM",
5268*4882a593Smuzhiyun 	"Speaker Front", "Speaker Surround", "Speaker CLFE", "Speaker Side",
5269*4882a593Smuzhiyun 	"Headphone Front", "Headphone Surround", "Headphone CLFE",
5270*4882a593Smuzhiyun 	"Headphone Side", "Headphone+LO", "Speaker+LO",
5271*4882a593Smuzhiyun 	NULL,
5272*4882a593Smuzhiyun };
5273*4882a593Smuzhiyun 
5274*4882a593Smuzhiyun /**
5275*4882a593Smuzhiyun  * snd_hda_gen_build_controls - Build controls from the parsed results
5276*4882a593Smuzhiyun  * @codec: the HDA codec
5277*4882a593Smuzhiyun  *
5278*4882a593Smuzhiyun  * Pass this to build_controls patch_ops.
5279*4882a593Smuzhiyun  */
snd_hda_gen_build_controls(struct hda_codec * codec)5280*4882a593Smuzhiyun int snd_hda_gen_build_controls(struct hda_codec *codec)
5281*4882a593Smuzhiyun {
5282*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5283*4882a593Smuzhiyun 	int err;
5284*4882a593Smuzhiyun 
5285*4882a593Smuzhiyun 	if (spec->kctls.used) {
5286*4882a593Smuzhiyun 		err = snd_hda_add_new_ctls(codec, spec->kctls.list);
5287*4882a593Smuzhiyun 		if (err < 0)
5288*4882a593Smuzhiyun 			return err;
5289*4882a593Smuzhiyun 	}
5290*4882a593Smuzhiyun 
5291*4882a593Smuzhiyun 	if (spec->multiout.dig_out_nid) {
5292*4882a593Smuzhiyun 		err = snd_hda_create_dig_out_ctls(codec,
5293*4882a593Smuzhiyun 						  spec->multiout.dig_out_nid,
5294*4882a593Smuzhiyun 						  spec->multiout.dig_out_nid,
5295*4882a593Smuzhiyun 						  spec->pcm_rec[1]->pcm_type);
5296*4882a593Smuzhiyun 		if (err < 0)
5297*4882a593Smuzhiyun 			return err;
5298*4882a593Smuzhiyun 		if (!spec->no_analog) {
5299*4882a593Smuzhiyun 			err = snd_hda_create_spdif_share_sw(codec,
5300*4882a593Smuzhiyun 							    &spec->multiout);
5301*4882a593Smuzhiyun 			if (err < 0)
5302*4882a593Smuzhiyun 				return err;
5303*4882a593Smuzhiyun 			spec->multiout.share_spdif = 1;
5304*4882a593Smuzhiyun 		}
5305*4882a593Smuzhiyun 	}
5306*4882a593Smuzhiyun 	if (spec->dig_in_nid) {
5307*4882a593Smuzhiyun 		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
5308*4882a593Smuzhiyun 		if (err < 0)
5309*4882a593Smuzhiyun 			return err;
5310*4882a593Smuzhiyun 	}
5311*4882a593Smuzhiyun 
5312*4882a593Smuzhiyun 	/* if we have no master control, let's create it */
5313*4882a593Smuzhiyun 	if (!spec->no_analog && !spec->suppress_vmaster &&
5314*4882a593Smuzhiyun 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
5315*4882a593Smuzhiyun 		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
5316*4882a593Smuzhiyun 					  spec->vmaster_tlv, follower_pfxs,
5317*4882a593Smuzhiyun 					  "Playback Volume");
5318*4882a593Smuzhiyun 		if (err < 0)
5319*4882a593Smuzhiyun 			return err;
5320*4882a593Smuzhiyun 	}
5321*4882a593Smuzhiyun 	if (!spec->no_analog && !spec->suppress_vmaster &&
5322*4882a593Smuzhiyun 	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
5323*4882a593Smuzhiyun 		err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
5324*4882a593Smuzhiyun 					    NULL, follower_pfxs,
5325*4882a593Smuzhiyun 					    "Playback Switch",
5326*4882a593Smuzhiyun 					    true, &spec->vmaster_mute.sw_kctl);
5327*4882a593Smuzhiyun 		if (err < 0)
5328*4882a593Smuzhiyun 			return err;
5329*4882a593Smuzhiyun 		if (spec->vmaster_mute.hook) {
5330*4882a593Smuzhiyun 			snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
5331*4882a593Smuzhiyun 						 spec->vmaster_mute_enum);
5332*4882a593Smuzhiyun 			snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
5333*4882a593Smuzhiyun 		}
5334*4882a593Smuzhiyun 	}
5335*4882a593Smuzhiyun 
5336*4882a593Smuzhiyun 	free_kctls(spec); /* no longer needed */
5337*4882a593Smuzhiyun 
5338*4882a593Smuzhiyun 	err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
5339*4882a593Smuzhiyun 	if (err < 0)
5340*4882a593Smuzhiyun 		return err;
5341*4882a593Smuzhiyun 
5342*4882a593Smuzhiyun 	return 0;
5343*4882a593Smuzhiyun }
5344*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_build_controls);
5345*4882a593Smuzhiyun 
5346*4882a593Smuzhiyun 
5347*4882a593Smuzhiyun /*
5348*4882a593Smuzhiyun  * PCM definitions
5349*4882a593Smuzhiyun  */
5350*4882a593Smuzhiyun 
call_pcm_playback_hook(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream,int action)5351*4882a593Smuzhiyun static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo,
5352*4882a593Smuzhiyun 				   struct hda_codec *codec,
5353*4882a593Smuzhiyun 				   struct snd_pcm_substream *substream,
5354*4882a593Smuzhiyun 				   int action)
5355*4882a593Smuzhiyun {
5356*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5357*4882a593Smuzhiyun 	if (spec->pcm_playback_hook)
5358*4882a593Smuzhiyun 		spec->pcm_playback_hook(hinfo, codec, substream, action);
5359*4882a593Smuzhiyun }
5360*4882a593Smuzhiyun 
call_pcm_capture_hook(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream,int action)5361*4882a593Smuzhiyun static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo,
5362*4882a593Smuzhiyun 				  struct hda_codec *codec,
5363*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream,
5364*4882a593Smuzhiyun 				  int action)
5365*4882a593Smuzhiyun {
5366*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5367*4882a593Smuzhiyun 	if (spec->pcm_capture_hook)
5368*4882a593Smuzhiyun 		spec->pcm_capture_hook(hinfo, codec, substream, action);
5369*4882a593Smuzhiyun }
5370*4882a593Smuzhiyun 
5371*4882a593Smuzhiyun /*
5372*4882a593Smuzhiyun  * Analog playback callbacks
5373*4882a593Smuzhiyun  */
playback_pcm_open(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5374*4882a593Smuzhiyun static int playback_pcm_open(struct hda_pcm_stream *hinfo,
5375*4882a593Smuzhiyun 			     struct hda_codec *codec,
5376*4882a593Smuzhiyun 			     struct snd_pcm_substream *substream)
5377*4882a593Smuzhiyun {
5378*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5379*4882a593Smuzhiyun 	int err;
5380*4882a593Smuzhiyun 
5381*4882a593Smuzhiyun 	mutex_lock(&spec->pcm_mutex);
5382*4882a593Smuzhiyun 	err = snd_hda_multi_out_analog_open(codec,
5383*4882a593Smuzhiyun 					    &spec->multiout, substream,
5384*4882a593Smuzhiyun 					     hinfo);
5385*4882a593Smuzhiyun 	if (!err) {
5386*4882a593Smuzhiyun 		spec->active_streams |= 1 << STREAM_MULTI_OUT;
5387*4882a593Smuzhiyun 		call_pcm_playback_hook(hinfo, codec, substream,
5388*4882a593Smuzhiyun 				       HDA_GEN_PCM_ACT_OPEN);
5389*4882a593Smuzhiyun 	}
5390*4882a593Smuzhiyun 	mutex_unlock(&spec->pcm_mutex);
5391*4882a593Smuzhiyun 	return err;
5392*4882a593Smuzhiyun }
5393*4882a593Smuzhiyun 
playback_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5394*4882a593Smuzhiyun static int playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5395*4882a593Smuzhiyun 				struct hda_codec *codec,
5396*4882a593Smuzhiyun 				unsigned int stream_tag,
5397*4882a593Smuzhiyun 				unsigned int format,
5398*4882a593Smuzhiyun 				struct snd_pcm_substream *substream)
5399*4882a593Smuzhiyun {
5400*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5401*4882a593Smuzhiyun 	int err;
5402*4882a593Smuzhiyun 
5403*4882a593Smuzhiyun 	err = snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
5404*4882a593Smuzhiyun 					       stream_tag, format, substream);
5405*4882a593Smuzhiyun 	if (!err)
5406*4882a593Smuzhiyun 		call_pcm_playback_hook(hinfo, codec, substream,
5407*4882a593Smuzhiyun 				       HDA_GEN_PCM_ACT_PREPARE);
5408*4882a593Smuzhiyun 	return err;
5409*4882a593Smuzhiyun }
5410*4882a593Smuzhiyun 
playback_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5411*4882a593Smuzhiyun static int playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5412*4882a593Smuzhiyun 				struct hda_codec *codec,
5413*4882a593Smuzhiyun 				struct snd_pcm_substream *substream)
5414*4882a593Smuzhiyun {
5415*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5416*4882a593Smuzhiyun 	int err;
5417*4882a593Smuzhiyun 
5418*4882a593Smuzhiyun 	err = snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
5419*4882a593Smuzhiyun 	if (!err)
5420*4882a593Smuzhiyun 		call_pcm_playback_hook(hinfo, codec, substream,
5421*4882a593Smuzhiyun 				       HDA_GEN_PCM_ACT_CLEANUP);
5422*4882a593Smuzhiyun 	return err;
5423*4882a593Smuzhiyun }
5424*4882a593Smuzhiyun 
playback_pcm_close(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5425*4882a593Smuzhiyun static int playback_pcm_close(struct hda_pcm_stream *hinfo,
5426*4882a593Smuzhiyun 			      struct hda_codec *codec,
5427*4882a593Smuzhiyun 			      struct snd_pcm_substream *substream)
5428*4882a593Smuzhiyun {
5429*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5430*4882a593Smuzhiyun 	mutex_lock(&spec->pcm_mutex);
5431*4882a593Smuzhiyun 	spec->active_streams &= ~(1 << STREAM_MULTI_OUT);
5432*4882a593Smuzhiyun 	call_pcm_playback_hook(hinfo, codec, substream,
5433*4882a593Smuzhiyun 			       HDA_GEN_PCM_ACT_CLOSE);
5434*4882a593Smuzhiyun 	mutex_unlock(&spec->pcm_mutex);
5435*4882a593Smuzhiyun 	return 0;
5436*4882a593Smuzhiyun }
5437*4882a593Smuzhiyun 
capture_pcm_open(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5438*4882a593Smuzhiyun static int capture_pcm_open(struct hda_pcm_stream *hinfo,
5439*4882a593Smuzhiyun 			    struct hda_codec *codec,
5440*4882a593Smuzhiyun 			    struct snd_pcm_substream *substream)
5441*4882a593Smuzhiyun {
5442*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN);
5443*4882a593Smuzhiyun 	return 0;
5444*4882a593Smuzhiyun }
5445*4882a593Smuzhiyun 
capture_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5446*4882a593Smuzhiyun static int capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5447*4882a593Smuzhiyun 			       struct hda_codec *codec,
5448*4882a593Smuzhiyun 			       unsigned int stream_tag,
5449*4882a593Smuzhiyun 			       unsigned int format,
5450*4882a593Smuzhiyun 			       struct snd_pcm_substream *substream)
5451*4882a593Smuzhiyun {
5452*4882a593Smuzhiyun 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5453*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream,
5454*4882a593Smuzhiyun 			      HDA_GEN_PCM_ACT_PREPARE);
5455*4882a593Smuzhiyun 	return 0;
5456*4882a593Smuzhiyun }
5457*4882a593Smuzhiyun 
capture_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5458*4882a593Smuzhiyun static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5459*4882a593Smuzhiyun 			       struct hda_codec *codec,
5460*4882a593Smuzhiyun 			       struct snd_pcm_substream *substream)
5461*4882a593Smuzhiyun {
5462*4882a593Smuzhiyun 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5463*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream,
5464*4882a593Smuzhiyun 			      HDA_GEN_PCM_ACT_CLEANUP);
5465*4882a593Smuzhiyun 	return 0;
5466*4882a593Smuzhiyun }
5467*4882a593Smuzhiyun 
capture_pcm_close(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5468*4882a593Smuzhiyun static int capture_pcm_close(struct hda_pcm_stream *hinfo,
5469*4882a593Smuzhiyun 			     struct hda_codec *codec,
5470*4882a593Smuzhiyun 			     struct snd_pcm_substream *substream)
5471*4882a593Smuzhiyun {
5472*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE);
5473*4882a593Smuzhiyun 	return 0;
5474*4882a593Smuzhiyun }
5475*4882a593Smuzhiyun 
alt_playback_pcm_open(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5476*4882a593Smuzhiyun static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
5477*4882a593Smuzhiyun 				 struct hda_codec *codec,
5478*4882a593Smuzhiyun 				 struct snd_pcm_substream *substream)
5479*4882a593Smuzhiyun {
5480*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5481*4882a593Smuzhiyun 	int err = 0;
5482*4882a593Smuzhiyun 
5483*4882a593Smuzhiyun 	mutex_lock(&spec->pcm_mutex);
5484*4882a593Smuzhiyun 	if (spec->indep_hp && !spec->indep_hp_enabled)
5485*4882a593Smuzhiyun 		err = -EBUSY;
5486*4882a593Smuzhiyun 	else
5487*4882a593Smuzhiyun 		spec->active_streams |= 1 << STREAM_INDEP_HP;
5488*4882a593Smuzhiyun 	call_pcm_playback_hook(hinfo, codec, substream,
5489*4882a593Smuzhiyun 			       HDA_GEN_PCM_ACT_OPEN);
5490*4882a593Smuzhiyun 	mutex_unlock(&spec->pcm_mutex);
5491*4882a593Smuzhiyun 	return err;
5492*4882a593Smuzhiyun }
5493*4882a593Smuzhiyun 
alt_playback_pcm_close(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5494*4882a593Smuzhiyun static int alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
5495*4882a593Smuzhiyun 				  struct hda_codec *codec,
5496*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream)
5497*4882a593Smuzhiyun {
5498*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5499*4882a593Smuzhiyun 	mutex_lock(&spec->pcm_mutex);
5500*4882a593Smuzhiyun 	spec->active_streams &= ~(1 << STREAM_INDEP_HP);
5501*4882a593Smuzhiyun 	call_pcm_playback_hook(hinfo, codec, substream,
5502*4882a593Smuzhiyun 			       HDA_GEN_PCM_ACT_CLOSE);
5503*4882a593Smuzhiyun 	mutex_unlock(&spec->pcm_mutex);
5504*4882a593Smuzhiyun 	return 0;
5505*4882a593Smuzhiyun }
5506*4882a593Smuzhiyun 
alt_playback_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5507*4882a593Smuzhiyun static int alt_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5508*4882a593Smuzhiyun 				    struct hda_codec *codec,
5509*4882a593Smuzhiyun 				    unsigned int stream_tag,
5510*4882a593Smuzhiyun 				    unsigned int format,
5511*4882a593Smuzhiyun 				    struct snd_pcm_substream *substream)
5512*4882a593Smuzhiyun {
5513*4882a593Smuzhiyun 	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
5514*4882a593Smuzhiyun 	call_pcm_playback_hook(hinfo, codec, substream,
5515*4882a593Smuzhiyun 			       HDA_GEN_PCM_ACT_PREPARE);
5516*4882a593Smuzhiyun 	return 0;
5517*4882a593Smuzhiyun }
5518*4882a593Smuzhiyun 
alt_playback_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5519*4882a593Smuzhiyun static int alt_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5520*4882a593Smuzhiyun 				    struct hda_codec *codec,
5521*4882a593Smuzhiyun 				    struct snd_pcm_substream *substream)
5522*4882a593Smuzhiyun {
5523*4882a593Smuzhiyun 	snd_hda_codec_cleanup_stream(codec, hinfo->nid);
5524*4882a593Smuzhiyun 	call_pcm_playback_hook(hinfo, codec, substream,
5525*4882a593Smuzhiyun 			       HDA_GEN_PCM_ACT_CLEANUP);
5526*4882a593Smuzhiyun 	return 0;
5527*4882a593Smuzhiyun }
5528*4882a593Smuzhiyun 
5529*4882a593Smuzhiyun /*
5530*4882a593Smuzhiyun  * Digital out
5531*4882a593Smuzhiyun  */
dig_playback_pcm_open(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5532*4882a593Smuzhiyun static int dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
5533*4882a593Smuzhiyun 				 struct hda_codec *codec,
5534*4882a593Smuzhiyun 				 struct snd_pcm_substream *substream)
5535*4882a593Smuzhiyun {
5536*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5537*4882a593Smuzhiyun 	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
5538*4882a593Smuzhiyun }
5539*4882a593Smuzhiyun 
dig_playback_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5540*4882a593Smuzhiyun static int dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
5541*4882a593Smuzhiyun 				    struct hda_codec *codec,
5542*4882a593Smuzhiyun 				    unsigned int stream_tag,
5543*4882a593Smuzhiyun 				    unsigned int format,
5544*4882a593Smuzhiyun 				    struct snd_pcm_substream *substream)
5545*4882a593Smuzhiyun {
5546*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5547*4882a593Smuzhiyun 	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
5548*4882a593Smuzhiyun 					     stream_tag, format, substream);
5549*4882a593Smuzhiyun }
5550*4882a593Smuzhiyun 
dig_playback_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5551*4882a593Smuzhiyun static int dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
5552*4882a593Smuzhiyun 				    struct hda_codec *codec,
5553*4882a593Smuzhiyun 				    struct snd_pcm_substream *substream)
5554*4882a593Smuzhiyun {
5555*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5556*4882a593Smuzhiyun 	return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
5557*4882a593Smuzhiyun }
5558*4882a593Smuzhiyun 
dig_playback_pcm_close(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5559*4882a593Smuzhiyun static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
5560*4882a593Smuzhiyun 				  struct hda_codec *codec,
5561*4882a593Smuzhiyun 				  struct snd_pcm_substream *substream)
5562*4882a593Smuzhiyun {
5563*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5564*4882a593Smuzhiyun 	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
5565*4882a593Smuzhiyun }
5566*4882a593Smuzhiyun 
5567*4882a593Smuzhiyun /*
5568*4882a593Smuzhiyun  * Analog capture
5569*4882a593Smuzhiyun  */
5570*4882a593Smuzhiyun #define alt_capture_pcm_open	capture_pcm_open
5571*4882a593Smuzhiyun #define alt_capture_pcm_close	capture_pcm_close
5572*4882a593Smuzhiyun 
alt_capture_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5573*4882a593Smuzhiyun static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5574*4882a593Smuzhiyun 				   struct hda_codec *codec,
5575*4882a593Smuzhiyun 				   unsigned int stream_tag,
5576*4882a593Smuzhiyun 				   unsigned int format,
5577*4882a593Smuzhiyun 				   struct snd_pcm_substream *substream)
5578*4882a593Smuzhiyun {
5579*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5580*4882a593Smuzhiyun 
5581*4882a593Smuzhiyun 	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1],
5582*4882a593Smuzhiyun 				   stream_tag, 0, format);
5583*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream,
5584*4882a593Smuzhiyun 			      HDA_GEN_PCM_ACT_PREPARE);
5585*4882a593Smuzhiyun 	return 0;
5586*4882a593Smuzhiyun }
5587*4882a593Smuzhiyun 
alt_capture_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5588*4882a593Smuzhiyun static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5589*4882a593Smuzhiyun 				   struct hda_codec *codec,
5590*4882a593Smuzhiyun 				   struct snd_pcm_substream *substream)
5591*4882a593Smuzhiyun {
5592*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5593*4882a593Smuzhiyun 
5594*4882a593Smuzhiyun 	snd_hda_codec_cleanup_stream(codec,
5595*4882a593Smuzhiyun 				     spec->adc_nids[substream->number + 1]);
5596*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream,
5597*4882a593Smuzhiyun 			      HDA_GEN_PCM_ACT_CLEANUP);
5598*4882a593Smuzhiyun 	return 0;
5599*4882a593Smuzhiyun }
5600*4882a593Smuzhiyun 
5601*4882a593Smuzhiyun /*
5602*4882a593Smuzhiyun  */
5603*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_analog_playback = {
5604*4882a593Smuzhiyun 	.substreams = 1,
5605*4882a593Smuzhiyun 	.channels_min = 2,
5606*4882a593Smuzhiyun 	.channels_max = 8,
5607*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5608*4882a593Smuzhiyun 	.ops = {
5609*4882a593Smuzhiyun 		.open = playback_pcm_open,
5610*4882a593Smuzhiyun 		.close = playback_pcm_close,
5611*4882a593Smuzhiyun 		.prepare = playback_pcm_prepare,
5612*4882a593Smuzhiyun 		.cleanup = playback_pcm_cleanup
5613*4882a593Smuzhiyun 	},
5614*4882a593Smuzhiyun };
5615*4882a593Smuzhiyun 
5616*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_analog_capture = {
5617*4882a593Smuzhiyun 	.substreams = 1,
5618*4882a593Smuzhiyun 	.channels_min = 2,
5619*4882a593Smuzhiyun 	.channels_max = 2,
5620*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5621*4882a593Smuzhiyun 	.ops = {
5622*4882a593Smuzhiyun 		.open = capture_pcm_open,
5623*4882a593Smuzhiyun 		.close = capture_pcm_close,
5624*4882a593Smuzhiyun 		.prepare = capture_pcm_prepare,
5625*4882a593Smuzhiyun 		.cleanup = capture_pcm_cleanup
5626*4882a593Smuzhiyun 	},
5627*4882a593Smuzhiyun };
5628*4882a593Smuzhiyun 
5629*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_analog_alt_playback = {
5630*4882a593Smuzhiyun 	.substreams = 1,
5631*4882a593Smuzhiyun 	.channels_min = 2,
5632*4882a593Smuzhiyun 	.channels_max = 2,
5633*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5634*4882a593Smuzhiyun 	.ops = {
5635*4882a593Smuzhiyun 		.open = alt_playback_pcm_open,
5636*4882a593Smuzhiyun 		.close = alt_playback_pcm_close,
5637*4882a593Smuzhiyun 		.prepare = alt_playback_pcm_prepare,
5638*4882a593Smuzhiyun 		.cleanup = alt_playback_pcm_cleanup
5639*4882a593Smuzhiyun 	},
5640*4882a593Smuzhiyun };
5641*4882a593Smuzhiyun 
5642*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_analog_alt_capture = {
5643*4882a593Smuzhiyun 	.substreams = 2, /* can be overridden */
5644*4882a593Smuzhiyun 	.channels_min = 2,
5645*4882a593Smuzhiyun 	.channels_max = 2,
5646*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5647*4882a593Smuzhiyun 	.ops = {
5648*4882a593Smuzhiyun 		.open = alt_capture_pcm_open,
5649*4882a593Smuzhiyun 		.close = alt_capture_pcm_close,
5650*4882a593Smuzhiyun 		.prepare = alt_capture_pcm_prepare,
5651*4882a593Smuzhiyun 		.cleanup = alt_capture_pcm_cleanup
5652*4882a593Smuzhiyun 	},
5653*4882a593Smuzhiyun };
5654*4882a593Smuzhiyun 
5655*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_digital_playback = {
5656*4882a593Smuzhiyun 	.substreams = 1,
5657*4882a593Smuzhiyun 	.channels_min = 2,
5658*4882a593Smuzhiyun 	.channels_max = 2,
5659*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5660*4882a593Smuzhiyun 	.ops = {
5661*4882a593Smuzhiyun 		.open = dig_playback_pcm_open,
5662*4882a593Smuzhiyun 		.close = dig_playback_pcm_close,
5663*4882a593Smuzhiyun 		.prepare = dig_playback_pcm_prepare,
5664*4882a593Smuzhiyun 		.cleanup = dig_playback_pcm_cleanup
5665*4882a593Smuzhiyun 	},
5666*4882a593Smuzhiyun };
5667*4882a593Smuzhiyun 
5668*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_digital_capture = {
5669*4882a593Smuzhiyun 	.substreams = 1,
5670*4882a593Smuzhiyun 	.channels_min = 2,
5671*4882a593Smuzhiyun 	.channels_max = 2,
5672*4882a593Smuzhiyun 	/* NID is set in build_pcms */
5673*4882a593Smuzhiyun };
5674*4882a593Smuzhiyun 
5675*4882a593Smuzhiyun /* Used by build_pcms to flag that a PCM has no playback stream */
5676*4882a593Smuzhiyun static const struct hda_pcm_stream pcm_null_stream = {
5677*4882a593Smuzhiyun 	.substreams = 0,
5678*4882a593Smuzhiyun 	.channels_min = 0,
5679*4882a593Smuzhiyun 	.channels_max = 0,
5680*4882a593Smuzhiyun };
5681*4882a593Smuzhiyun 
5682*4882a593Smuzhiyun /*
5683*4882a593Smuzhiyun  * dynamic changing ADC PCM streams
5684*4882a593Smuzhiyun  */
dyn_adc_pcm_resetup(struct hda_codec * codec,int cur)5685*4882a593Smuzhiyun static bool dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
5686*4882a593Smuzhiyun {
5687*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5688*4882a593Smuzhiyun 	hda_nid_t new_adc = spec->adc_nids[spec->dyn_adc_idx[cur]];
5689*4882a593Smuzhiyun 
5690*4882a593Smuzhiyun 	if (spec->cur_adc && spec->cur_adc != new_adc) {
5691*4882a593Smuzhiyun 		/* stream is running, let's swap the current ADC */
5692*4882a593Smuzhiyun 		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
5693*4882a593Smuzhiyun 		spec->cur_adc = new_adc;
5694*4882a593Smuzhiyun 		snd_hda_codec_setup_stream(codec, new_adc,
5695*4882a593Smuzhiyun 					   spec->cur_adc_stream_tag, 0,
5696*4882a593Smuzhiyun 					   spec->cur_adc_format);
5697*4882a593Smuzhiyun 		return true;
5698*4882a593Smuzhiyun 	}
5699*4882a593Smuzhiyun 	return false;
5700*4882a593Smuzhiyun }
5701*4882a593Smuzhiyun 
5702*4882a593Smuzhiyun /* analog capture with dynamic dual-adc changes */
dyn_adc_capture_pcm_prepare(struct hda_pcm_stream * hinfo,struct hda_codec * codec,unsigned int stream_tag,unsigned int format,struct snd_pcm_substream * substream)5703*4882a593Smuzhiyun static int dyn_adc_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
5704*4882a593Smuzhiyun 				       struct hda_codec *codec,
5705*4882a593Smuzhiyun 				       unsigned int stream_tag,
5706*4882a593Smuzhiyun 				       unsigned int format,
5707*4882a593Smuzhiyun 				       struct snd_pcm_substream *substream)
5708*4882a593Smuzhiyun {
5709*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5710*4882a593Smuzhiyun 	spec->cur_adc = spec->adc_nids[spec->dyn_adc_idx[spec->cur_mux[0]]];
5711*4882a593Smuzhiyun 	spec->cur_adc_stream_tag = stream_tag;
5712*4882a593Smuzhiyun 	spec->cur_adc_format = format;
5713*4882a593Smuzhiyun 	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
5714*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_PREPARE);
5715*4882a593Smuzhiyun 	return 0;
5716*4882a593Smuzhiyun }
5717*4882a593Smuzhiyun 
dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream * hinfo,struct hda_codec * codec,struct snd_pcm_substream * substream)5718*4882a593Smuzhiyun static int dyn_adc_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
5719*4882a593Smuzhiyun 				       struct hda_codec *codec,
5720*4882a593Smuzhiyun 				       struct snd_pcm_substream *substream)
5721*4882a593Smuzhiyun {
5722*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5723*4882a593Smuzhiyun 	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
5724*4882a593Smuzhiyun 	spec->cur_adc = 0;
5725*4882a593Smuzhiyun 	call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLEANUP);
5726*4882a593Smuzhiyun 	return 0;
5727*4882a593Smuzhiyun }
5728*4882a593Smuzhiyun 
5729*4882a593Smuzhiyun static const struct hda_pcm_stream dyn_adc_pcm_analog_capture = {
5730*4882a593Smuzhiyun 	.substreams = 1,
5731*4882a593Smuzhiyun 	.channels_min = 2,
5732*4882a593Smuzhiyun 	.channels_max = 2,
5733*4882a593Smuzhiyun 	.nid = 0, /* fill later */
5734*4882a593Smuzhiyun 	.ops = {
5735*4882a593Smuzhiyun 		.prepare = dyn_adc_capture_pcm_prepare,
5736*4882a593Smuzhiyun 		.cleanup = dyn_adc_capture_pcm_cleanup
5737*4882a593Smuzhiyun 	},
5738*4882a593Smuzhiyun };
5739*4882a593Smuzhiyun 
fill_pcm_stream_name(char * str,size_t len,const char * sfx,const char * chip_name)5740*4882a593Smuzhiyun static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
5741*4882a593Smuzhiyun 				 const char *chip_name)
5742*4882a593Smuzhiyun {
5743*4882a593Smuzhiyun 	char *p;
5744*4882a593Smuzhiyun 
5745*4882a593Smuzhiyun 	if (*str)
5746*4882a593Smuzhiyun 		return;
5747*4882a593Smuzhiyun 	strlcpy(str, chip_name, len);
5748*4882a593Smuzhiyun 
5749*4882a593Smuzhiyun 	/* drop non-alnum chars after a space */
5750*4882a593Smuzhiyun 	for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
5751*4882a593Smuzhiyun 		if (!isalnum(p[1])) {
5752*4882a593Smuzhiyun 			*p = 0;
5753*4882a593Smuzhiyun 			break;
5754*4882a593Smuzhiyun 		}
5755*4882a593Smuzhiyun 	}
5756*4882a593Smuzhiyun 	strlcat(str, sfx, len);
5757*4882a593Smuzhiyun }
5758*4882a593Smuzhiyun 
5759*4882a593Smuzhiyun /* copy PCM stream info from @default_str, and override non-NULL entries
5760*4882a593Smuzhiyun  * from @spec_str and @nid
5761*4882a593Smuzhiyun  */
setup_pcm_stream(struct hda_pcm_stream * str,const struct hda_pcm_stream * default_str,const struct hda_pcm_stream * spec_str,hda_nid_t nid)5762*4882a593Smuzhiyun static void setup_pcm_stream(struct hda_pcm_stream *str,
5763*4882a593Smuzhiyun 			     const struct hda_pcm_stream *default_str,
5764*4882a593Smuzhiyun 			     const struct hda_pcm_stream *spec_str,
5765*4882a593Smuzhiyun 			     hda_nid_t nid)
5766*4882a593Smuzhiyun {
5767*4882a593Smuzhiyun 	*str = *default_str;
5768*4882a593Smuzhiyun 	if (nid)
5769*4882a593Smuzhiyun 		str->nid = nid;
5770*4882a593Smuzhiyun 	if (spec_str) {
5771*4882a593Smuzhiyun 		if (spec_str->substreams)
5772*4882a593Smuzhiyun 			str->substreams = spec_str->substreams;
5773*4882a593Smuzhiyun 		if (spec_str->channels_min)
5774*4882a593Smuzhiyun 			str->channels_min = spec_str->channels_min;
5775*4882a593Smuzhiyun 		if (spec_str->channels_max)
5776*4882a593Smuzhiyun 			str->channels_max = spec_str->channels_max;
5777*4882a593Smuzhiyun 		if (spec_str->rates)
5778*4882a593Smuzhiyun 			str->rates = spec_str->rates;
5779*4882a593Smuzhiyun 		if (spec_str->formats)
5780*4882a593Smuzhiyun 			str->formats = spec_str->formats;
5781*4882a593Smuzhiyun 		if (spec_str->maxbps)
5782*4882a593Smuzhiyun 			str->maxbps = spec_str->maxbps;
5783*4882a593Smuzhiyun 	}
5784*4882a593Smuzhiyun }
5785*4882a593Smuzhiyun 
5786*4882a593Smuzhiyun /**
5787*4882a593Smuzhiyun  * snd_hda_gen_build_pcms - build PCM streams based on the parsed results
5788*4882a593Smuzhiyun  * @codec: the HDA codec
5789*4882a593Smuzhiyun  *
5790*4882a593Smuzhiyun  * Pass this to build_pcms patch_ops.
5791*4882a593Smuzhiyun  */
snd_hda_gen_build_pcms(struct hda_codec * codec)5792*4882a593Smuzhiyun int snd_hda_gen_build_pcms(struct hda_codec *codec)
5793*4882a593Smuzhiyun {
5794*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5795*4882a593Smuzhiyun 	struct hda_pcm *info;
5796*4882a593Smuzhiyun 	bool have_multi_adcs;
5797*4882a593Smuzhiyun 
5798*4882a593Smuzhiyun 	if (spec->no_analog)
5799*4882a593Smuzhiyun 		goto skip_analog;
5800*4882a593Smuzhiyun 
5801*4882a593Smuzhiyun 	fill_pcm_stream_name(spec->stream_name_analog,
5802*4882a593Smuzhiyun 			     sizeof(spec->stream_name_analog),
5803*4882a593Smuzhiyun 			     " Analog", codec->core.chip_name);
5804*4882a593Smuzhiyun 	info = snd_hda_codec_pcm_new(codec, "%s", spec->stream_name_analog);
5805*4882a593Smuzhiyun 	if (!info)
5806*4882a593Smuzhiyun 		return -ENOMEM;
5807*4882a593Smuzhiyun 	spec->pcm_rec[0] = info;
5808*4882a593Smuzhiyun 
5809*4882a593Smuzhiyun 	if (spec->multiout.num_dacs > 0) {
5810*4882a593Smuzhiyun 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5811*4882a593Smuzhiyun 				 &pcm_analog_playback,
5812*4882a593Smuzhiyun 				 spec->stream_analog_playback,
5813*4882a593Smuzhiyun 				 spec->multiout.dac_nids[0]);
5814*4882a593Smuzhiyun 		info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
5815*4882a593Smuzhiyun 			spec->multiout.max_channels;
5816*4882a593Smuzhiyun 		if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT &&
5817*4882a593Smuzhiyun 		    spec->autocfg.line_outs == 2)
5818*4882a593Smuzhiyun 			info->stream[SNDRV_PCM_STREAM_PLAYBACK].chmap =
5819*4882a593Smuzhiyun 				snd_pcm_2_1_chmaps;
5820*4882a593Smuzhiyun 	}
5821*4882a593Smuzhiyun 	if (spec->num_adc_nids) {
5822*4882a593Smuzhiyun 		setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5823*4882a593Smuzhiyun 				 (spec->dyn_adc_switch ?
5824*4882a593Smuzhiyun 				  &dyn_adc_pcm_analog_capture : &pcm_analog_capture),
5825*4882a593Smuzhiyun 				 spec->stream_analog_capture,
5826*4882a593Smuzhiyun 				 spec->adc_nids[0]);
5827*4882a593Smuzhiyun 	}
5828*4882a593Smuzhiyun 
5829*4882a593Smuzhiyun  skip_analog:
5830*4882a593Smuzhiyun 	/* SPDIF for stream index #1 */
5831*4882a593Smuzhiyun 	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
5832*4882a593Smuzhiyun 		fill_pcm_stream_name(spec->stream_name_digital,
5833*4882a593Smuzhiyun 				     sizeof(spec->stream_name_digital),
5834*4882a593Smuzhiyun 				     " Digital", codec->core.chip_name);
5835*4882a593Smuzhiyun 		info = snd_hda_codec_pcm_new(codec, "%s",
5836*4882a593Smuzhiyun 					     spec->stream_name_digital);
5837*4882a593Smuzhiyun 		if (!info)
5838*4882a593Smuzhiyun 			return -ENOMEM;
5839*4882a593Smuzhiyun 		codec->follower_dig_outs = spec->multiout.follower_dig_outs;
5840*4882a593Smuzhiyun 		spec->pcm_rec[1] = info;
5841*4882a593Smuzhiyun 		if (spec->dig_out_type)
5842*4882a593Smuzhiyun 			info->pcm_type = spec->dig_out_type;
5843*4882a593Smuzhiyun 		else
5844*4882a593Smuzhiyun 			info->pcm_type = HDA_PCM_TYPE_SPDIF;
5845*4882a593Smuzhiyun 		if (spec->multiout.dig_out_nid)
5846*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5847*4882a593Smuzhiyun 					 &pcm_digital_playback,
5848*4882a593Smuzhiyun 					 spec->stream_digital_playback,
5849*4882a593Smuzhiyun 					 spec->multiout.dig_out_nid);
5850*4882a593Smuzhiyun 		if (spec->dig_in_nid)
5851*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5852*4882a593Smuzhiyun 					 &pcm_digital_capture,
5853*4882a593Smuzhiyun 					 spec->stream_digital_capture,
5854*4882a593Smuzhiyun 					 spec->dig_in_nid);
5855*4882a593Smuzhiyun 	}
5856*4882a593Smuzhiyun 
5857*4882a593Smuzhiyun 	if (spec->no_analog)
5858*4882a593Smuzhiyun 		return 0;
5859*4882a593Smuzhiyun 
5860*4882a593Smuzhiyun 	/* If the use of more than one ADC is requested for the current
5861*4882a593Smuzhiyun 	 * model, configure a second analog capture-only PCM.
5862*4882a593Smuzhiyun 	 */
5863*4882a593Smuzhiyun 	have_multi_adcs = (spec->num_adc_nids > 1) &&
5864*4882a593Smuzhiyun 		!spec->dyn_adc_switch && !spec->auto_mic;
5865*4882a593Smuzhiyun 	/* Additional Analaog capture for index #2 */
5866*4882a593Smuzhiyun 	if (spec->alt_dac_nid || have_multi_adcs) {
5867*4882a593Smuzhiyun 		fill_pcm_stream_name(spec->stream_name_alt_analog,
5868*4882a593Smuzhiyun 				     sizeof(spec->stream_name_alt_analog),
5869*4882a593Smuzhiyun 			     " Alt Analog", codec->core.chip_name);
5870*4882a593Smuzhiyun 		info = snd_hda_codec_pcm_new(codec, "%s",
5871*4882a593Smuzhiyun 					     spec->stream_name_alt_analog);
5872*4882a593Smuzhiyun 		if (!info)
5873*4882a593Smuzhiyun 			return -ENOMEM;
5874*4882a593Smuzhiyun 		spec->pcm_rec[2] = info;
5875*4882a593Smuzhiyun 		if (spec->alt_dac_nid)
5876*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5877*4882a593Smuzhiyun 					 &pcm_analog_alt_playback,
5878*4882a593Smuzhiyun 					 spec->stream_analog_alt_playback,
5879*4882a593Smuzhiyun 					 spec->alt_dac_nid);
5880*4882a593Smuzhiyun 		else
5881*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_PLAYBACK],
5882*4882a593Smuzhiyun 					 &pcm_null_stream, NULL, 0);
5883*4882a593Smuzhiyun 		if (have_multi_adcs) {
5884*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5885*4882a593Smuzhiyun 					 &pcm_analog_alt_capture,
5886*4882a593Smuzhiyun 					 spec->stream_analog_alt_capture,
5887*4882a593Smuzhiyun 					 spec->adc_nids[1]);
5888*4882a593Smuzhiyun 			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
5889*4882a593Smuzhiyun 				spec->num_adc_nids - 1;
5890*4882a593Smuzhiyun 		} else {
5891*4882a593Smuzhiyun 			setup_pcm_stream(&info->stream[SNDRV_PCM_STREAM_CAPTURE],
5892*4882a593Smuzhiyun 					 &pcm_null_stream, NULL, 0);
5893*4882a593Smuzhiyun 		}
5894*4882a593Smuzhiyun 	}
5895*4882a593Smuzhiyun 
5896*4882a593Smuzhiyun 	return 0;
5897*4882a593Smuzhiyun }
5898*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_build_pcms);
5899*4882a593Smuzhiyun 
5900*4882a593Smuzhiyun 
5901*4882a593Smuzhiyun /*
5902*4882a593Smuzhiyun  * Standard auto-parser initializations
5903*4882a593Smuzhiyun  */
5904*4882a593Smuzhiyun 
5905*4882a593Smuzhiyun /* configure the given path as a proper output */
set_output_and_unmute(struct hda_codec * codec,int path_idx)5906*4882a593Smuzhiyun static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
5907*4882a593Smuzhiyun {
5908*4882a593Smuzhiyun 	struct nid_path *path;
5909*4882a593Smuzhiyun 	hda_nid_t pin;
5910*4882a593Smuzhiyun 
5911*4882a593Smuzhiyun 	path = snd_hda_get_path_from_idx(codec, path_idx);
5912*4882a593Smuzhiyun 	if (!path || !path->depth)
5913*4882a593Smuzhiyun 		return;
5914*4882a593Smuzhiyun 	pin = path->path[path->depth - 1];
5915*4882a593Smuzhiyun 	restore_pin_ctl(codec, pin);
5916*4882a593Smuzhiyun 	snd_hda_activate_path(codec, path, path->active,
5917*4882a593Smuzhiyun 			      aamix_default(codec->spec));
5918*4882a593Smuzhiyun 	set_pin_eapd(codec, pin, path->active);
5919*4882a593Smuzhiyun }
5920*4882a593Smuzhiyun 
5921*4882a593Smuzhiyun /* initialize primary output paths */
init_multi_out(struct hda_codec * codec)5922*4882a593Smuzhiyun static void init_multi_out(struct hda_codec *codec)
5923*4882a593Smuzhiyun {
5924*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5925*4882a593Smuzhiyun 	int i;
5926*4882a593Smuzhiyun 
5927*4882a593Smuzhiyun 	for (i = 0; i < spec->autocfg.line_outs; i++)
5928*4882a593Smuzhiyun 		set_output_and_unmute(codec, spec->out_paths[i]);
5929*4882a593Smuzhiyun }
5930*4882a593Smuzhiyun 
5931*4882a593Smuzhiyun 
__init_extra_out(struct hda_codec * codec,int num_outs,int * paths)5932*4882a593Smuzhiyun static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
5933*4882a593Smuzhiyun {
5934*4882a593Smuzhiyun 	int i;
5935*4882a593Smuzhiyun 
5936*4882a593Smuzhiyun 	for (i = 0; i < num_outs; i++)
5937*4882a593Smuzhiyun 		set_output_and_unmute(codec, paths[i]);
5938*4882a593Smuzhiyun }
5939*4882a593Smuzhiyun 
5940*4882a593Smuzhiyun /* initialize hp and speaker paths */
init_extra_out(struct hda_codec * codec)5941*4882a593Smuzhiyun static void init_extra_out(struct hda_codec *codec)
5942*4882a593Smuzhiyun {
5943*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5944*4882a593Smuzhiyun 
5945*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
5946*4882a593Smuzhiyun 		__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
5947*4882a593Smuzhiyun 	if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
5948*4882a593Smuzhiyun 		__init_extra_out(codec, spec->autocfg.speaker_outs,
5949*4882a593Smuzhiyun 				 spec->speaker_paths);
5950*4882a593Smuzhiyun }
5951*4882a593Smuzhiyun 
5952*4882a593Smuzhiyun /* initialize multi-io paths */
init_multi_io(struct hda_codec * codec)5953*4882a593Smuzhiyun static void init_multi_io(struct hda_codec *codec)
5954*4882a593Smuzhiyun {
5955*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5956*4882a593Smuzhiyun 	int i;
5957*4882a593Smuzhiyun 
5958*4882a593Smuzhiyun 	for (i = 0; i < spec->multi_ios; i++) {
5959*4882a593Smuzhiyun 		hda_nid_t pin = spec->multi_io[i].pin;
5960*4882a593Smuzhiyun 		struct nid_path *path;
5961*4882a593Smuzhiyun 		path = get_multiio_path(codec, i);
5962*4882a593Smuzhiyun 		if (!path)
5963*4882a593Smuzhiyun 			continue;
5964*4882a593Smuzhiyun 		if (!spec->multi_io[i].ctl_in)
5965*4882a593Smuzhiyun 			spec->multi_io[i].ctl_in =
5966*4882a593Smuzhiyun 				snd_hda_codec_get_pin_target(codec, pin);
5967*4882a593Smuzhiyun 		snd_hda_activate_path(codec, path, path->active,
5968*4882a593Smuzhiyun 				      aamix_default(spec));
5969*4882a593Smuzhiyun 	}
5970*4882a593Smuzhiyun }
5971*4882a593Smuzhiyun 
init_aamix_paths(struct hda_codec * codec)5972*4882a593Smuzhiyun static void init_aamix_paths(struct hda_codec *codec)
5973*4882a593Smuzhiyun {
5974*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5975*4882a593Smuzhiyun 
5976*4882a593Smuzhiyun 	if (!spec->have_aamix_ctl)
5977*4882a593Smuzhiyun 		return;
5978*4882a593Smuzhiyun 	if (!has_aamix_out_paths(spec))
5979*4882a593Smuzhiyun 		return;
5980*4882a593Smuzhiyun 	update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
5981*4882a593Smuzhiyun 			   spec->aamix_out_paths[0],
5982*4882a593Smuzhiyun 			   spec->autocfg.line_out_type);
5983*4882a593Smuzhiyun 	update_aamix_paths(codec, spec->aamix_mode, spec->hp_paths[0],
5984*4882a593Smuzhiyun 			   spec->aamix_out_paths[1],
5985*4882a593Smuzhiyun 			   AUTO_PIN_HP_OUT);
5986*4882a593Smuzhiyun 	update_aamix_paths(codec, spec->aamix_mode, spec->speaker_paths[0],
5987*4882a593Smuzhiyun 			   spec->aamix_out_paths[2],
5988*4882a593Smuzhiyun 			   AUTO_PIN_SPEAKER_OUT);
5989*4882a593Smuzhiyun }
5990*4882a593Smuzhiyun 
5991*4882a593Smuzhiyun /* set up input pins and loopback paths */
init_analog_input(struct hda_codec * codec)5992*4882a593Smuzhiyun static void init_analog_input(struct hda_codec *codec)
5993*4882a593Smuzhiyun {
5994*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
5995*4882a593Smuzhiyun 	struct auto_pin_cfg *cfg = &spec->autocfg;
5996*4882a593Smuzhiyun 	int i;
5997*4882a593Smuzhiyun 
5998*4882a593Smuzhiyun 	for (i = 0; i < cfg->num_inputs; i++) {
5999*4882a593Smuzhiyun 		hda_nid_t nid = cfg->inputs[i].pin;
6000*4882a593Smuzhiyun 		if (is_input_pin(codec, nid))
6001*4882a593Smuzhiyun 			restore_pin_ctl(codec, nid);
6002*4882a593Smuzhiyun 
6003*4882a593Smuzhiyun 		/* init loopback inputs */
6004*4882a593Smuzhiyun 		if (spec->mixer_nid) {
6005*4882a593Smuzhiyun 			resume_path_from_idx(codec, spec->loopback_paths[i]);
6006*4882a593Smuzhiyun 			resume_path_from_idx(codec, spec->loopback_merge_path);
6007*4882a593Smuzhiyun 		}
6008*4882a593Smuzhiyun 	}
6009*4882a593Smuzhiyun }
6010*4882a593Smuzhiyun 
6011*4882a593Smuzhiyun /* initialize ADC paths */
init_input_src(struct hda_codec * codec)6012*4882a593Smuzhiyun static void init_input_src(struct hda_codec *codec)
6013*4882a593Smuzhiyun {
6014*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
6015*4882a593Smuzhiyun 	struct hda_input_mux *imux = &spec->input_mux;
6016*4882a593Smuzhiyun 	struct nid_path *path;
6017*4882a593Smuzhiyun 	int i, c, nums;
6018*4882a593Smuzhiyun 
6019*4882a593Smuzhiyun 	if (spec->dyn_adc_switch)
6020*4882a593Smuzhiyun 		nums = 1;
6021*4882a593Smuzhiyun 	else
6022*4882a593Smuzhiyun 		nums = spec->num_adc_nids;
6023*4882a593Smuzhiyun 
6024*4882a593Smuzhiyun 	for (c = 0; c < nums; c++) {
6025*4882a593Smuzhiyun 		for (i = 0; i < imux->num_items; i++) {
6026*4882a593Smuzhiyun 			path = get_input_path(codec, c, i);
6027*4882a593Smuzhiyun 			if (path) {
6028*4882a593Smuzhiyun 				bool active = path->active;
6029*4882a593Smuzhiyun 				if (i == spec->cur_mux[c])
6030*4882a593Smuzhiyun 					active = true;
6031*4882a593Smuzhiyun 				snd_hda_activate_path(codec, path, active, false);
6032*4882a593Smuzhiyun 			}
6033*4882a593Smuzhiyun 		}
6034*4882a593Smuzhiyun 		if (spec->hp_mic)
6035*4882a593Smuzhiyun 			update_hp_mic(codec, c, true);
6036*4882a593Smuzhiyun 	}
6037*4882a593Smuzhiyun 
6038*4882a593Smuzhiyun 	if (spec->cap_sync_hook)
6039*4882a593Smuzhiyun 		spec->cap_sync_hook(codec, NULL, NULL);
6040*4882a593Smuzhiyun }
6041*4882a593Smuzhiyun 
6042*4882a593Smuzhiyun /* set right pin controls for digital I/O */
init_digital(struct hda_codec * codec)6043*4882a593Smuzhiyun static void init_digital(struct hda_codec *codec)
6044*4882a593Smuzhiyun {
6045*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
6046*4882a593Smuzhiyun 	int i;
6047*4882a593Smuzhiyun 	hda_nid_t pin;
6048*4882a593Smuzhiyun 
6049*4882a593Smuzhiyun 	for (i = 0; i < spec->autocfg.dig_outs; i++)
6050*4882a593Smuzhiyun 		set_output_and_unmute(codec, spec->digout_paths[i]);
6051*4882a593Smuzhiyun 	pin = spec->autocfg.dig_in_pin;
6052*4882a593Smuzhiyun 	if (pin) {
6053*4882a593Smuzhiyun 		restore_pin_ctl(codec, pin);
6054*4882a593Smuzhiyun 		resume_path_from_idx(codec, spec->digin_path);
6055*4882a593Smuzhiyun 	}
6056*4882a593Smuzhiyun }
6057*4882a593Smuzhiyun 
6058*4882a593Smuzhiyun /* clear unsol-event tags on unused pins; Conexant codecs seem to leave
6059*4882a593Smuzhiyun  * invalid unsol tags by some reason
6060*4882a593Smuzhiyun  */
clear_unsol_on_unused_pins(struct hda_codec * codec)6061*4882a593Smuzhiyun static void clear_unsol_on_unused_pins(struct hda_codec *codec)
6062*4882a593Smuzhiyun {
6063*4882a593Smuzhiyun 	const struct hda_pincfg *pin;
6064*4882a593Smuzhiyun 	int i;
6065*4882a593Smuzhiyun 
6066*4882a593Smuzhiyun 	snd_array_for_each(&codec->init_pins, i, pin) {
6067*4882a593Smuzhiyun 		hda_nid_t nid = pin->nid;
6068*4882a593Smuzhiyun 		if (is_jack_detectable(codec, nid) &&
6069*4882a593Smuzhiyun 		    !snd_hda_jack_tbl_get(codec, nid))
6070*4882a593Smuzhiyun 			snd_hda_codec_write_cache(codec, nid, 0,
6071*4882a593Smuzhiyun 					AC_VERB_SET_UNSOLICITED_ENABLE, 0);
6072*4882a593Smuzhiyun 	}
6073*4882a593Smuzhiyun }
6074*4882a593Smuzhiyun 
6075*4882a593Smuzhiyun /**
6076*4882a593Smuzhiyun  * snd_hda_gen_init - initialize the generic spec
6077*4882a593Smuzhiyun  * @codec: the HDA codec
6078*4882a593Smuzhiyun  *
6079*4882a593Smuzhiyun  * This can be put as patch_ops init function.
6080*4882a593Smuzhiyun  */
snd_hda_gen_init(struct hda_codec * codec)6081*4882a593Smuzhiyun int snd_hda_gen_init(struct hda_codec *codec)
6082*4882a593Smuzhiyun {
6083*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
6084*4882a593Smuzhiyun 
6085*4882a593Smuzhiyun 	if (spec->init_hook)
6086*4882a593Smuzhiyun 		spec->init_hook(codec);
6087*4882a593Smuzhiyun 
6088*4882a593Smuzhiyun 	if (!spec->skip_verbs)
6089*4882a593Smuzhiyun 		snd_hda_apply_verbs(codec);
6090*4882a593Smuzhiyun 
6091*4882a593Smuzhiyun 	init_multi_out(codec);
6092*4882a593Smuzhiyun 	init_extra_out(codec);
6093*4882a593Smuzhiyun 	init_multi_io(codec);
6094*4882a593Smuzhiyun 	init_aamix_paths(codec);
6095*4882a593Smuzhiyun 	init_analog_input(codec);
6096*4882a593Smuzhiyun 	init_input_src(codec);
6097*4882a593Smuzhiyun 	init_digital(codec);
6098*4882a593Smuzhiyun 
6099*4882a593Smuzhiyun 	clear_unsol_on_unused_pins(codec);
6100*4882a593Smuzhiyun 
6101*4882a593Smuzhiyun 	sync_all_pin_power_ctls(codec);
6102*4882a593Smuzhiyun 
6103*4882a593Smuzhiyun 	/* call init functions of standard auto-mute helpers */
6104*4882a593Smuzhiyun 	update_automute_all(codec);
6105*4882a593Smuzhiyun 
6106*4882a593Smuzhiyun 	snd_hda_regmap_sync(codec);
6107*4882a593Smuzhiyun 
6108*4882a593Smuzhiyun 	if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
6109*4882a593Smuzhiyun 		snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
6110*4882a593Smuzhiyun 
6111*4882a593Smuzhiyun 	hda_call_check_power_status(codec, 0x01);
6112*4882a593Smuzhiyun 	return 0;
6113*4882a593Smuzhiyun }
6114*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_init);
6115*4882a593Smuzhiyun 
6116*4882a593Smuzhiyun /**
6117*4882a593Smuzhiyun  * snd_hda_gen_free - free the generic spec
6118*4882a593Smuzhiyun  * @codec: the HDA codec
6119*4882a593Smuzhiyun  *
6120*4882a593Smuzhiyun  * This can be put as patch_ops free function.
6121*4882a593Smuzhiyun  */
snd_hda_gen_free(struct hda_codec * codec)6122*4882a593Smuzhiyun void snd_hda_gen_free(struct hda_codec *codec)
6123*4882a593Smuzhiyun {
6124*4882a593Smuzhiyun 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_FREE);
6125*4882a593Smuzhiyun 	snd_hda_gen_spec_free(codec->spec);
6126*4882a593Smuzhiyun 	kfree(codec->spec);
6127*4882a593Smuzhiyun 	codec->spec = NULL;
6128*4882a593Smuzhiyun }
6129*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_free);
6130*4882a593Smuzhiyun 
6131*4882a593Smuzhiyun /**
6132*4882a593Smuzhiyun  * snd_hda_gen_reboot_notify - Make codec enter D3 before rebooting
6133*4882a593Smuzhiyun  * @codec: the HDA codec
6134*4882a593Smuzhiyun  *
6135*4882a593Smuzhiyun  * This can be put as patch_ops reboot_notify function.
6136*4882a593Smuzhiyun  */
snd_hda_gen_reboot_notify(struct hda_codec * codec)6137*4882a593Smuzhiyun void snd_hda_gen_reboot_notify(struct hda_codec *codec)
6138*4882a593Smuzhiyun {
6139*4882a593Smuzhiyun 	/* Make the codec enter D3 to avoid spurious noises from the internal
6140*4882a593Smuzhiyun 	 * speaker during (and after) reboot
6141*4882a593Smuzhiyun 	 */
6142*4882a593Smuzhiyun 	snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
6143*4882a593Smuzhiyun 	snd_hda_codec_write(codec, codec->core.afg, 0,
6144*4882a593Smuzhiyun 			    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
6145*4882a593Smuzhiyun 	msleep(10);
6146*4882a593Smuzhiyun }
6147*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_reboot_notify);
6148*4882a593Smuzhiyun 
6149*4882a593Smuzhiyun #ifdef CONFIG_PM
6150*4882a593Smuzhiyun /**
6151*4882a593Smuzhiyun  * snd_hda_gen_check_power_status - check the loopback power save state
6152*4882a593Smuzhiyun  * @codec: the HDA codec
6153*4882a593Smuzhiyun  * @nid: NID to inspect
6154*4882a593Smuzhiyun  *
6155*4882a593Smuzhiyun  * This can be put as patch_ops check_power_status function.
6156*4882a593Smuzhiyun  */
snd_hda_gen_check_power_status(struct hda_codec * codec,hda_nid_t nid)6157*4882a593Smuzhiyun int snd_hda_gen_check_power_status(struct hda_codec *codec, hda_nid_t nid)
6158*4882a593Smuzhiyun {
6159*4882a593Smuzhiyun 	struct hda_gen_spec *spec = codec->spec;
6160*4882a593Smuzhiyun 	return snd_hda_check_amp_list_power(codec, &spec->loopback, nid);
6161*4882a593Smuzhiyun }
6162*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_hda_gen_check_power_status);
6163*4882a593Smuzhiyun #endif
6164*4882a593Smuzhiyun 
6165*4882a593Smuzhiyun 
6166*4882a593Smuzhiyun /*
6167*4882a593Smuzhiyun  * the generic codec support
6168*4882a593Smuzhiyun  */
6169*4882a593Smuzhiyun 
6170*4882a593Smuzhiyun static const struct hda_codec_ops generic_patch_ops = {
6171*4882a593Smuzhiyun 	.build_controls = snd_hda_gen_build_controls,
6172*4882a593Smuzhiyun 	.build_pcms = snd_hda_gen_build_pcms,
6173*4882a593Smuzhiyun 	.init = snd_hda_gen_init,
6174*4882a593Smuzhiyun 	.free = snd_hda_gen_free,
6175*4882a593Smuzhiyun 	.unsol_event = snd_hda_jack_unsol_event,
6176*4882a593Smuzhiyun 	.reboot_notify = snd_hda_gen_reboot_notify,
6177*4882a593Smuzhiyun #ifdef CONFIG_PM
6178*4882a593Smuzhiyun 	.check_power_status = snd_hda_gen_check_power_status,
6179*4882a593Smuzhiyun #endif
6180*4882a593Smuzhiyun };
6181*4882a593Smuzhiyun 
6182*4882a593Smuzhiyun /*
6183*4882a593Smuzhiyun  * snd_hda_parse_generic_codec - Generic codec parser
6184*4882a593Smuzhiyun  * @codec: the HDA codec
6185*4882a593Smuzhiyun  */
snd_hda_parse_generic_codec(struct hda_codec * codec)6186*4882a593Smuzhiyun static int snd_hda_parse_generic_codec(struct hda_codec *codec)
6187*4882a593Smuzhiyun {
6188*4882a593Smuzhiyun 	struct hda_gen_spec *spec;
6189*4882a593Smuzhiyun 	int err;
6190*4882a593Smuzhiyun 
6191*4882a593Smuzhiyun 	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6192*4882a593Smuzhiyun 	if (!spec)
6193*4882a593Smuzhiyun 		return -ENOMEM;
6194*4882a593Smuzhiyun 	snd_hda_gen_spec_init(spec);
6195*4882a593Smuzhiyun 	codec->spec = spec;
6196*4882a593Smuzhiyun 
6197*4882a593Smuzhiyun 	err = snd_hda_parse_pin_defcfg(codec, &spec->autocfg, NULL, 0);
6198*4882a593Smuzhiyun 	if (err < 0)
6199*4882a593Smuzhiyun 		goto error;
6200*4882a593Smuzhiyun 
6201*4882a593Smuzhiyun 	err = snd_hda_gen_parse_auto_config(codec, &spec->autocfg);
6202*4882a593Smuzhiyun 	if (err < 0)
6203*4882a593Smuzhiyun 		goto error;
6204*4882a593Smuzhiyun 
6205*4882a593Smuzhiyun 	codec->patch_ops = generic_patch_ops;
6206*4882a593Smuzhiyun 	return 0;
6207*4882a593Smuzhiyun 
6208*4882a593Smuzhiyun error:
6209*4882a593Smuzhiyun 	snd_hda_gen_free(codec);
6210*4882a593Smuzhiyun 	return err;
6211*4882a593Smuzhiyun }
6212*4882a593Smuzhiyun 
6213*4882a593Smuzhiyun static const struct hda_device_id snd_hda_id_generic[] = {
6214*4882a593Smuzhiyun 	HDA_CODEC_ENTRY(HDA_CODEC_ID_GENERIC, "Generic", snd_hda_parse_generic_codec),
6215*4882a593Smuzhiyun 	{} /* terminator */
6216*4882a593Smuzhiyun };
6217*4882a593Smuzhiyun MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_generic);
6218*4882a593Smuzhiyun 
6219*4882a593Smuzhiyun static struct hda_codec_driver generic_driver = {
6220*4882a593Smuzhiyun 	.id = snd_hda_id_generic,
6221*4882a593Smuzhiyun };
6222*4882a593Smuzhiyun 
6223*4882a593Smuzhiyun module_hda_codec_driver(generic_driver);
6224*4882a593Smuzhiyun 
6225*4882a593Smuzhiyun MODULE_LICENSE("GPL");
6226*4882a593Smuzhiyun MODULE_DESCRIPTION("Generic HD-audio codec parser");
6227